SessionStart hook on resume can report `hook timed out after 60s` even when the hook exits 0 in ~4s
On Windows, Codex CLI resumed a session and showed:
SessionStart hook (failed)error: hook timed out after 60s
For that same resumed session:
- the outer
SessionStartwrapper finishedexit=0in4085ms - the inner hook finished
outcome=successin3218ms - the session was still
runningimmediately afterward
This looks like a false or misattributed SessionStart timeout banner on the
resume path rather than a real 60s timeout of the successful hook invocation.
Environment
- Codex CLI:
0.128.0 - OS: Windows 10
- Shell: PowerShell 7
- Terminal emulator: Windows Terminal
[features].codex_hooks = true[features].tui_app_server = true- Hook type:
SessionStartcommand hook - Configured
SessionStarttimeout:60
Hook Setup
The specimen was taken with a SessionStart command hook configured attimeout: 60.
The hook ran through a PowerShell wrapper that:
- logged start/end timing
- synchronously invoked the real hook work
- exited with the real hook result
Sanitized shape:
config.toml
[features]
codex_hooks = true
tui_app_server = true
hooks.json
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "& \"<sessionstart-wrapper>.ps1\"",
"timeout": 60
}
]
}
]
}
}
Observed
On resume, Codex displayed the failure banner above.
For the same resumed session id, local timing showed:
phase=start ... sessionId=<resumed-session-id> source=resume
phase=end ... sessionId=<resumed-session-id> source=resume exit=0 elapsedMs=4085
For that same resumed session id, the inner hook log showed:
event=SessionStart outcome=success ... sessionId=<resumed-session-id> ... totalMs=3218
Immediately afterward, a direct status check for that same resumed session id
returned:
{
"found": true,
"sessionId": "<resumed-session-id>",
"state": "running"
}
Minimal Repro Shape
I do not yet have a tiny standalone repro outside my normal setup, but the
observed shape is:
- Enable a
SessionStartcommand hook on Windows. - Set
timeoutto60. - Run the hook through a wrapper that logs timing and then invokes the real
hook synchronously.
- Resume an existing Codex session.
- Observe that Codex may display:
SessionStart hook (failed)error: hook timed out after 60s
- Compare the banner against hook-side timing for the same resumed session id.
In this specimen, hook-side timing contradicted the UI banner.
Expected
- If the hook really times out, the same resumed-session invocation should not
later show successful completion.
- If the hook completes successfully well inside the timeout window, Codex
should not show a timeout failure banner for that resumed session.
Evidence
1. User-visible failure
The terminal UI displayed:
SessionStart hook (failed)
error: hook timed out after 60s
2. Outer wrapper completed successfully for the resumed session
phase=start ... sessionId=<resumed-session-id> source=resume
phase=end ... sessionId=<resumed-session-id> source=resume exit=0 elapsedMs=4085
3. Inner hook completed successfully for the same resumed session
event=SessionStart outcome=success ... sessionId=<resumed-session-id> ... totalMs=3218
4. The resumed session was still running afterward
{
"found": true,
"sessionId": "<resumed-session-id>",
"state": "running"
}
Possible Clue
Secondary clue only, not required for the main claim:
- A separate startup-path wrapper invocation on a different internal session id
exited quickly with code 1.
- That may explain the wrong banner attribution if Codex is mixing startup-path
and resume-path hook outcomes internally.
Suspected Issue
Codex may be surfacing stale SessionStart failure state on resume, or
attributing a different startup-path hook outcome to the resumed session UI.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗