anthropics / anthropics/claude-code

[BUG] stream-json: result event omits the `result` field entirely after a control_request interrupt

Open
#94,741 0 comments 0 reactions 0 assignees View on GitHub
area:cli area:core bug has repro platform:macos
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (nearest: #86001 and #88608 cover interrupt *semantics*; #78686 covers `.result` content 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):

```bash
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):

```jsonl
{"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: ""` (or `result: null`) on interrupted turns; or
- document that interrupted result events omit `result`, and add an explicit discriminator clients can branch on (`interrupted: true` or `terminal_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)

Contributor guide

No contributing guide indexed for this repository

Research direction

No source files or tests are named. Start by running the provided stream-json command and comparing the normal and interrupted terminal result events, then trace the code that emits those events. Done means interrupted results have a stable documented shape or an explicit discriminator, with coverage for the reproduced control_request case.

Written by the indexing model from the issue text.

Assessment

Tech stack
json, python
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.