Headless -p session exits when a turn ends while a background task is the only pending wake signal

Status Open
Reported on v2.1.228
Maintainer reply None cached
Activity 0 comments · opened Aug 19, 2026

Environment

  • Claude Code 2.1.228 and 2.1.232 (reproduced on both), Linux x86_64
  • Non-interactive: claude -p "<prompt>" --output-format stream-json --verbose, launched detached (nohup … &, stdin /dev/null)

Bug

In a headless -p session, if the model ends its turn while a harness background task (a Bash call with run_in_background, or a background subagent) is still running and is the session's only pending wake source, the process exits at end of turn instead of staying alive and re-invoking the model when the task notification arrives. In interactive mode the same situation re-wakes the conversation normally.

Measured twice in one day (2026-08-13), same signature both times in the stream-json tail:

  1. the last assistant text is a mid-work status message (the model clearly intended to continue after the background task finished — no final answer/result marker it had been instructed to emit),
  2. followed by trailing background-task lifecycle events,
  3. then process exit with a result object.

Consequences: any OS child processes the session was tracking are orphaned, and the session's final wrap-up work never happens — the session is lost mid-flight rather than completing.

Expected

Either (a) a -p session with pending tracked background tasks stays alive and delivers the completion notification as a new turn, matching interactive behavior, or (b) the end-of-turn/exit contract for print mode with pending background tasks is documented so harness authors know a turn must never end while a background task is the only wake signal.

Workaround we use

Launch long-running children as detached OS processes and hold a synchronous foreground wait loop inside a single turn (poll pid liveness + output-file mtime, sleep inside the loop); never end a turn with a pending harness background task. This works but forfeits background-task ergonomics in exactly the sessions that need them most.

View original on GitHub ↗