[BUG] stream-json: result event omits the `result` field entirely after a control_request interrupt
Status Open
Reported on v2.1.273
Maintainer reply None cached
Activity 0 comments · opened Sep 16, 2026
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (nearest: #86001 and #88608 cover interrupt semantics; #78686 covers
.resultcontent truncation; none cover the key being absent) - [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
In a --input-format stream-json --output-format stream-json session, interrupting a running Bash tool with a control_request produces a terminal type: result event that has no result key at all. Every other terminal result event carries a string result. A consumer that treats event.result as always-present throws on an otherwise ordinary terminal event, and nothing in the docs says the key can be omitted.
Repro (default login, no API key):
env -u ANTHROPIC_API_KEY claude -p \
--input-format stream-json --output-format stream-json --verbose \
--model sonnet --permission-mode acceptEdits --permission-prompts none \
--allowedTools 'Bash(sleep *)'
stdin, three lines (the third sent while the sleep is running):
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Reply with exactly: probe-1"}]}}
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Run Bash sleep 5, then reply FINAL"}]}}
{"type":"control_request","request":{"subtype":"interrupt","request_id":"wh-int-1"}}
What Should Happen?
A stable result-event schema across all terminal events. Any of these would do:
- emit
result: ""(orresult: null) on interrupted turns; or - document that interrupted result events omit
result, and add an explicit discriminator clients can branch on (interrupted: trueorterminal_reason: "interrupted") instead of probing for key presence.
Error Messages/Logs
# first turn: result present
{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","stop_reason":"end_turn","num_turns":1,"result_index":0,"result":"probe-1"}
# interrupt acknowledged
{"type":"control_response","response":{"subtype":"success","request_id":"wh-int-1","response":{"still_queued":[]}}}
{"type":"user","content":[{"type":"text","text":"[Request interrupted by user for tool use]"}]}
# terminal event for the interrupted turn: no "result" key
{"type":"result","subtype":"error_during_execution","is_error":true,"terminal_reason":"aborted_tools","stop_reason":"tool_use","num_turns":3,"result_index":4,"errors":["[ede_diagnostic] result_type=user last_content_type=n/a stop_reason=tool_use"]}
Environment
- Claude Code 2.1.273 (reproduced), macOS 15
- Model: sonnet
- Consumer: a stream-json driver for long-running headless sessions (we now guard for the missing key; filing so the shape is documented or made stable)