Skip to content

Session resume fails with HTTP 400 when crash leaves orphaned tool call followed by tool result #217

@ckrabach617

Description

@ckrabach617

Summary

When a session crashes mid-tool-execution, resuming it fails with an Anthropic HTTP 400 error due to consecutive user-role messages in the API request. This creates an unresumable session that requires manual transcript surgery to fix.

Affected component: amplifier-core (session resume logic)

Reproduction

  1. Start a session with tool use
  2. Session crashes mid-tool-execution (network timeout, process kill, etc.) — leaving an assistant message with tool_calls but no corresponding tool_result in the transcript
  3. Attempt to resume the session with amplifier session resume <id>
  4. HTTP 400 from Anthropic

Root Cause

The resume logic strips orphaned assistant tool_use messages (correctly — can't send tool_use without tool_result). However, this leaves the preceding tool_result as the effective last message, which maps to role: "user" in the Anthropic API. The resume prompt is then appended as another role: "user" message, creating consecutive same-role messages that Anthropic rejects.

The sequence that fails:

[N-1] user (tool_result)     ← was paired with the now-stripped tool_use
[N]   user (resume prompt)   ← injected by resume logic
→ HTTP 400: consecutive user messages

A similar collision occurs when hooks (e.g., hooks-status-context) inject user-role content between a tool_result and the next API call.

Observed Impact

  • Session ba107234-91eb-403f-a671-a668a3f614de required four manual transcript repairs due to this bug
  • Each resume attempt hit HTTP 400, crashed again, and left additional corrupt state
  • The only workaround is manual transcript truncation back to a safe assistant text message with no pending tool calls

Suggested Fix

When constructing the API request for a resumed session:

  1. After stripping orphaned tool calls, check if the effective last message is role: "user"
  2. If so, either:
    • Merge the resume prompt into the existing user message, OR
    • Insert a synthetic assistant acknowledgment (e.g., "Resuming session.") before the resume prompt to maintain role alternation
  3. Apply the same merge logic when hooks inject user-role content after a tool_result

More generally, the message construction pipeline should enforce role alternation as a post-processing step before sending to any provider that requires it.

Environment

  • Platform: WSL2 (Linux 6.6.87.2-microsoft-standard-WSL2)
  • Provider: Anthropic (claude-opus-4-6)
  • Session: ba107234-91eb-403f-a671-a668a3f614de

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions