claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Missing Final Result Event in Streaming JSON Output with sdk

Open allisoneer opened this issue 7 months ago • 0 comments

Bug Description

Summary

Claude Code CLI fails to send the required final {"type":"result",...} event in streaming JSON mode after successful tool execution, causing the process to hang indefinitely despite completing the conversation functionally.

Environment

  • Claude Code Version: v1.0.18
  • Output Format: --output-format stream-json
  • Usage: Via Go SDK wrapper (https://github.com/humanlayer/humanlayer/tree/main/claudecode-go) which follows the official SDK specification

Reproduction

This bug is intermittent - same query patterns sometimes work, sometimes hang:

Working execution (session dae3c2a4-1abf-4e77-99c2-1e3de1a8ac4a):

  • Same multi-line TUI analysis query
  • Proper completion with final result event

Hanging execution (session e025afdd-d550-4718-acd5-21f01edbb244):

  • Identical query pattern and tool execution
  • Missing final result event, process hangs

Evidence of Claude Code Bug

1. SDK Specification Violation

Per official SDK docs:

"Each conversation begins with an initial init system message, followed by a list of user and assistant messages, followed by a final result system message with stats."

2. Event Sequence Comparison

✅ Working Session Event Sequence:

{"type":"system","subtype":"init","session_id":"...","tools":[...]}
{"type":"assistant","message":{"content":[{"type":"text","text":"..."}]}}
{"type":"assistant","message":{"content":[{"type":"tool_use","id":"...","name":"TodoWrite",...}]}}
{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"...","content":"..."}]}}
{"type":"result","subtype":"success","session_id":"...","cost_usd":2.90831585,"num_turns":62,...}

❌ Hanging Session Event Sequence:

{"type":"system","subtype":"init","session_id":"...","tools":[...]}
{"type":"assistant","message":{"content":[{"type":"text","text":"..."}]}}
{"type":"assistant","message":{"content":[{"type":"tool_use","id":"...","name":"TodoWrite",...}]}}
{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"...","content":"..."}]}}
// <-- MISSING: No {"type":"result",...} event, process hangs here

3. Go SDK Implementation Verification

Our Go wrapper correctly implements the SDK specification:

// Wait for BOTH process termination AND stdout parsing completion
go func() {
    session.SetError(cmd.Wait())  // Wait for process exit
    <-parseDone                   // Wait for stdout EOF + parsing complete
    close(session.done)           // Only then signal completion
}()

The SDK properly waits for Claude Code to:

  1. Send the final result event
  2. Close stdout
  3. Exit the process

Since Claude Code never sends step 1, steps 2-3 never happen.

4. Process State Evidence

# Process still running 30+ minutes after functional completion
$ ps aux | grep 89349
allison  89349  node .../claude --print "..." --output-format stream-json

Impact

  • SDK integration sessions hang indefinitely
  • Process accumulation over time
  • Daemon sessions show as "running" when functionally complete (daemon layer: https://github.com/humanlayer/humanlayer/tree/main/hld)
  • Prevents reliable automation with Claude Code

Workaround Attempted

Adding timeouts to detect hung processes, but this is clearly a Claude Code CLI issue that should be fixed upstream.

Additional Context

  • Bug appears to be related to tool execution completion handling in streaming mode
  • Both successful and hanging sessions involve the same TodoWrite tool
  • Functional completion occurs (response provided, tool executed successfully)
  • Only the final signaling is broken

Session IDs for Investigation

  • Working: dae3c2a4-1abf-4e77-99c2-1e3de1a8ac4a (bug report filed from the session by doing --resume interactively after the sdk run completed) / Claude session 70c4f4f8-5aff-401e-8e0a-782f8613ae8d
  • Hanging: e025afdd-d550-4718-acd5-21f01edbb244 (session not available to resume, showing claude code also doesn't believe it's finsihed) / Claude session c31fdd13-0cd4-4eb3-8349-f7ef23a55135

Raw event data available upon request for debugging.

Repository Context

This bug was discovered while developing a Claude Code integration for the HumanLayer project (https://github.com/humanlayer/humanlayer), which includes:

  • claudecode-go: Go SDK wrapper for Claude Code CLI
  • hld: Daemon layer that manages Claude Code sessions and stores conversation events

Environment Info

  • Platform: macos
  • Terminal: ghostty
  • Version: 1.0.18
  • Feedback ID: 0ed3e58e-bf98-46af-b0eb-9ff633e66a3f

Errors

[]

allisoneer avatar Jun 11 '25 00:06 allisoneer