From 4aa7119d7db7261519848fb5a14de47f39518bdc Mon Sep 17 00:00:00 2001 From: Alan T Miller <183872+alantmiller@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:59:53 -0700 Subject: [PATCH] fix: remove dead USER_MESSAGE_ONLY exit code that caused SessionStart hook errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The USER_MESSAGE_ONLY (exit code 3) constant was used by the old user-message-hook.js (removed in the hooks refactor). Claude Code only recognizes exit codes 0 (success) and 2 (blocking error) — any other non-zero exit code is treated as a hook failure, causing the "SessionStart:startup hook error" message on every session start for users still running v8.x. This removes the dead constant and improves the exit code documentation to prevent reintroduction. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/shared/hook-constants.ts | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/shared/hook-constants.ts b/src/shared/hook-constants.ts index c194921a..cfaf297c 100644 --- a/src/shared/hook-constants.ts +++ b/src/shared/hook-constants.ts @@ -1,13 +1,13 @@ export const HOOK_TIMEOUTS = { - DEFAULT: 300000, // Standard HTTP timeout (5 min for slow systems) - HEALTH_CHECK: 3000, // Worker health check (3s — healthy worker responds in <100ms) - POST_SPAWN_WAIT: 5000, // Wait for daemon to start after spawn (starts in <1s on Linux) - READINESS_WAIT: 30000, // Wait for DB + search init after spawn (typically <5s) - PORT_IN_USE_WAIT: 3000, // Wait when port occupied but health failing + DEFAULT: 300000, // Standard HTTP timeout (5 min for slow systems) + HEALTH_CHECK: 3000, // Worker health check (3s — healthy worker responds in <100ms) + POST_SPAWN_WAIT: 5000, // Wait for daemon to start after spawn (starts in <1s on Linux) + READINESS_WAIT: 30000, // Wait for DB + search init after spawn (typically <5s) + PORT_IN_USE_WAIT: 3000, // Wait when port occupied but health failing WORKER_STARTUP_WAIT: 1000, - PRE_RESTART_SETTLE_DELAY: 2000, // Give files time to sync before restart - POWERSHELL_COMMAND: 10000, // PowerShell process enumeration (10s - typically completes in <1s) - WINDOWS_MULTIPLIER: 1.5 // Platform-specific adjustment for hook-side operations + PRE_RESTART_SETTLE_DELAY: 2000, // Give files time to sync before restart + POWERSHELL_COMMAND: 10000, // PowerShell process enumeration (10s - typically completes in <1s) + WINDOWS_MULTIPLIER: 1.5, // Platform-specific adjustment for hook-side operations } as const; /** @@ -16,19 +16,21 @@ export const HOOK_TIMEOUTS = { * Exit code behavior per Claude Code docs: * - 0: Success. For SessionStart/UserPromptSubmit, stdout added to context. * - 2: Blocking error. For SessionStart, stderr shown to user only. - * - Other non-zero: stderr shown in verbose mode only. + * - Other non-zero: treated as hook error (stderr shown in verbose mode only). + * + * IMPORTANT: Only exit codes 0 and 2 are recognized by Claude Code. + * Any other non-zero exit code (including 1, 3, etc.) is treated as a + * hook failure and triggers the "hook error" UI message on every session start. */ export const HOOK_EXIT_CODES = { SUCCESS: 0, FAILURE: 1, /** Blocking error - for SessionStart, shows stderr to user only */ BLOCKING_ERROR: 2, - /** Show stderr to user only, don't inject into context. Used by user-message handler (Cursor). */ - USER_MESSAGE_ONLY: 3, } as const; export function getTimeout(baseTimeout: number): number { - return process.platform === 'win32' + return process.platform === "win32" ? Math.round(baseTimeout * HOOK_TIMEOUTS.WINDOWS_MULTIPLIER) : baseTimeout; }