UserPromptSubmit hook timeout is hardcoded to 30s (HN4=30000) with no override; context silently dropped on timeout
Environment: Claude Code 2.1.170, Linux, Max plan
Problem
UserPromptSubmit hooks are bounded by a hardcoded 30 s timeout with no override, and when a hook exceeds it the injected context is silently dropped — no warning to the user or the hook author.
In the 2.1.170 binary this is visible as:
var i5 = 600000, HN4 = 30000;
// UserPromptSubmit path:
yield* aP({ hookInput, toolUseID, signal, timeoutMs: HN4 /* = 30000 */ })
HN4 is a plain literal — no process.env read. Most other hook events use i5 = 600000 (600 s); UserPromptSubmit is special-cased to 30 s. The per-hook timeout field in settings.json does not raise this: it only bounds the child process (H.timeoutMs ?? TR1), while the event-level abort at 30 s wins. So there is no setting or env var that lets a power user extend it.
Why it matters
additionalContext injection is a documented, supported extension point. Workflows that compute ranked file/memory context per turn (RAG-style, multi-project, cognitive-mesh setups) can legitimately need >30 s on a cold cache or a large index. When the hook is killed at 30 s, the entire turn's injected context is lost, and the failure is invisible — it looks like "the model just didn't get my context," which is extremely hard to diagnose.
Request (any one would help)
- Make the
UserPromptSubmitevent-level timeout configurable — honor the existing per-hooktimeoutfield, or addCLAUDE_CODE_USER_PROMPT_HOOK_TIMEOUT_MS(parallel toCLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS, which already exists). - On hook timeout, surface a visible warning (e.g. a transcript notice) instead of silently dropping the injected context.
- At minimum, document the 30 s special-case for
UserPromptSubmitand the silent-drop-on-timeout behavior.
Note
An earlier version of this report mentioned a "10,000-character cap" on hook output. After inspecting the 2.1.170 binary directly I could not find such a cap on additionalContext — the operative constraint is the 30 s timeout above. Correcting the record so the ask is precise.