Skip to content

Tool use id bug #5750

Closed as not planned
Closed as not planned

Description

@leoisadev1

Description

I uploaded 2 images and a short message, got hit with this error.

Image

OpenCode version

1.0.167

Steps to reproduce

  1. Upload 2 images with ctrl + v
  2. Add a short message
  3. Click enter

Screenshot and/or share link

Image

Operating System

macOS 26.2

Terminal

Ghostty

Activity

  1. github-actions commented on Dec 18, 2025

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Feel free to ignore if none of these address your specific case.

  2. self-assigned this
    on Dec 18, 2025
  3. rekram1-node commented on Dec 18, 2025

    @rekram1-node
    Contributor

    ill look into it

  4. rekram1-node commented on Dec 18, 2025

    @rekram1-node
    Contributor
    Image

    How do I replicate?

    I saw ur description but I think this prolly has to do w/ ordering and whatnot

    If u could export session: opencode export > session.json it'd be amazing

  5. deriegle commented on Dec 19, 2025

    @deriegle

    https://gist.github.com/deriegle/db117ea51f6f55e814e855541bcd47ee

    I ran into this too. I had a longer session and was on the main branch in my repo. I had a few files staged and ran /rmslop (same as in opencode) and ran into this bug. I opened a new session and ran /rmslop and got the error again. The gist above is from the second session.

    Image

    EDIT: realizing the way mine happened was different (no images uploaded) but the error was similar in case that's helpful. Otherwise we can mark this as unrelated.

  6. rekram1-node commented on Dec 19, 2025

    @rekram1-node
    Contributor

    @deriegle can u give me the raw json export tho? opencode export > session.json

  7. deriegle commented on Dec 19, 2025

    @deriegle

    Sorry about that. I've added the session.json into this gist: https://gist.github.com/deriegle/db117ea51f6f55e814e855541bcd47ee

    Several of the calls outputted my entire files since it was diffing them, I obfuscated the file names & outputs. If those end up being required to debug this, I can find another way to share that.

  8. Mishkun commented on Dec 23, 2025

    @Mishkun
    Contributor

    https://gist.github.com/Mishkun/02648359700010e559f7edf6bc8ac4dd

    @rekram1-node I finally got this on a pet project, so I can share one in the full

  9. westito commented on Jan 8, 2026

    @westito

    I get this error many times so logged out and tried investigate with Opus. What I found.
    (I posted this on other issue, but marked as off-topic - this issue is more related)

    Tool Validation Error: Missing tool_result After Interruption

    Root Cause

    Client doesn't insert tool_result message after interruption before allowing model to continue.

    When abort happens, client appends retry to the SAME assistant message instead of starting a new turn with tool_result in between.

    Summary

    Anthropic's Messages API rejects conversation history when an assistant message contains content (thinking/text) AFTER a tool_use block. The API expects tool_result immediately after tool_use, but when content appears in between, validation fails.

    Error Message

    messages.{N}: `tool_use` ids were found without `tool_result` blocks immediately after: {tool_id}. 
    Each `tool_use` block must have a corresponding `tool_result` block in the next message.
    

    The Rule

    All tool_use blocks must be contiguous at the END of the assistant message content.

    Once a tool_use block appears, only more tool_use blocks can follow. Any other content (thinking, text) AFTER a tool_use is invalid.

    Valid vs Invalid Patterns

    Valid: Tools grouped at end

    assistant: [thinking, text, tool_use_A, tool_use_B]
    user: [tool_result_A, tool_result_B]
    

    Valid: Separate turns per tool

    assistant: [thinking, text, tool_use_A]
    user: [tool_result_A]
    assistant: [thinking, text, tool_use_B]
    user: [tool_result_B]
    

    Invalid: Content AFTER tool_use

    assistant: [thinking, tool_use_A, thinking, tool_use_B]  ← thinking AFTER tool_A!
    user: [tool_result_A, tool_result_B]
    

    Error: tool_use ids were found without tool_result blocks immediately after: tool_A

    The API sees content after tool_use_A and interprets it as: "tool_A should have gotten its result before the assistant generated more content."

    How This Happens

    When a user aborts a tool mid-stream:

    What should happen:

    assistant: [thinking, tool_A]       ← END turn here
    user: [tool_result_A: "aborted"]    ← INSERT this
    assistant: [thinking, tool_B]       ← NEW turn
    user: [tool_result_B]
    

    What actually happens:

    assistant: [thinking, tool_A, thinking, tool_B]  ← appended to SAME message
    user: [tool_result_A, tool_result_B]             ← both results bundled
    

    The sequence:

    1. Model generates: thinking → tool_A
    2. User aborts during tool execution
    3. Client saves: thinking → tool_A (aborted)
    4. BUG: Client does NOT end turn and add tool_result
    5. Model retries, client appends: thinking → tool_B
    6. Result: [thinking, tool_A, thinking, tool_B] - invalid pattern

    Other causes:

    • Network interruption during streaming
    • Timeout kills the stream
    • Client crash during streaming
    • Rate limiting mid-response

    Real-World Example

    Saved message parts

    prt_..5001 → step-start
    prt_..7001 → reasoning: "The user wants me to create a markdown file..."
    prt_..6001 → tool: write (ERROR, input: {})  ← ABORTED
    prt_..b001 → reasoning: "The user wants me to create a markdown file..."
    prt_..7001 → tool: write (COMPLETED)
    prt_..c001 → step-finish
    

    Converted to API format:

    {
      "role": "assistant",
      "content": [
        {"type": "thinking", "thinking": "..."},
        {"type": "tool_use", "id": "toolu_01LiPBp", "name": "write", "input": {}},
        {"type": "thinking", "thinking": "..."},
        {"type": "tool_use", "id": "toolu_016rCwe", "name": "write", "input": {...}}
      ]
    }

    API Error:

    messages.49: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01LiPBp
    

    Workaround

    Before sending to API, restructure messages with interleaved content:

    Option A - Split into separate turns:

    Original: assistant[thinking, tool_A, thinking, tool_B] + user[result_A, result_B]
    
    Fixed:
      assistant[thinking, tool_A] + user[result_A]
      assistant[thinking, tool_B] + user[result_B]
    

    Option B - Group tools at end (if results exist):

    Original: [thinking, tool_A, thinking, tool_B]
    
    Fixed: [thinking, thinking, tool_A, tool_B]
    

    Note: Only works if the tool results are bundled together in the next message.

    Test Results

    Pattern Result
    [thinking, text, tool_A, tool_B] → [result_A, result_B] ✅ SUCCESS
    [thinking, tool_A, thinking, tool_B] → [result_A, result_B] ❌ FAILED
    [thinking, text, tool_A, thinking, text, tool_B] → [result_A, result_B] ❌ FAILED
    [thinking, text, tool_A] → [result_A] → [thinking, text, tool_B] → [result_B] ✅ SUCCESS

    Minimal Reproduction

    curl -X POST https://api.anthropic.com/v1/messages \
      -H "x-api-key: $ANTHROPIC_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -H "anthropic-beta: interleaved-thinking-2025-05-14" \
      -H "content-type: application/json" \
      -d '{
        "model": "claude-sonnet-4-20250514",
        "max_tokens": 2048,
        "thinking": {"type": "enabled", "budget_tokens": 1024},
        "messages": [
          {"role": "user", "content": "Do two things"},
          {
            "role": "assistant",
            "content": [
              {"type": "thinking", "thinking": "First.", "signature": "VALID_SIG_HERE"},
              {"type": "tool_use", "id": "tool_1", "name": "do_thing", "input": {"x": 1}},
              {"type": "thinking", "thinking": "Second.", "signature": "VALID_SIG_HERE"},
              {"type": "tool_use", "id": "tool_2", "name": "do_thing", "input": {"x": 2}}
            ]
          },
          {
            "role": "user",
            "content": [
              {"type": "tool_result", "tool_use_id": "tool_1", "content": "done"},
              {"type": "tool_result", "tool_use_id": "tool_2", "content": "done"}
            ]
          }
        ],
        "tools": [{"name": "do_thing", "description": "Do", "input_schema": {"type": "object", "properties": {"x": {"type": "integer"}}}}]
      }'

    Expected error:

    {
      "type": "error",
      "error": {
        "type": "invalid_request_error",
        "message": "messages.1: `tool_use` ids were found without `tool_result` blocks immediately after: tool_1"
      }
    }
  10. prolific commented on Feb 12, 2026

    @prolific

    I am also getting this error way too many times. Makes the current session completely unusable.

  11. ArchishmanSengupta commented on Mar 26, 2026

    @ArchishmanSengupta

    is there any update on this? i can't use the session anymore after this error comes. this is very bad and customer facing issue.

  12. XedinUnknown commented on Apr 1, 2026

    @XedinUnknown

    Same problem. #2214 seems to be a duplicate. I used Serena MCP when it did that.

  13. faileon commented on Apr 28, 2026

    @faileon

    Same issue on latest OC 1.14.28
    after running /compact there is a high chance the session will get corrupted with:

    messages.2: tool_use ids were found without tool_result blocks immediately after: toolu_01FcmYRSCKCYMzixsRUwQbbt. Each tool_use block must have a corresponding tool_result block in the next message.

    only workaround is to export session and reference it in a new one via @ to try and preserve the context

  14. removed
    bugSomething isn't working
    on May 3, 2026
  15. viiqswim commented on Jun 29, 2026

    @viiqswim

    If the error you got is the "tool_use ids were found without tool_result blocks" 400, that's a pretty common one after an interrupted tool call, and attachment/image turns seem to trigger it too. I made a small plugin that prevents it and recovers from it automatically:

    https://github.com/viiqswim/opencode-compaction-guard

    One line in opencode.json:

    "plugin": ["opencode-compaction-guard@latest"]

    It cleans up dangling pending/running tool calls before each request, and if the 400 still happens it reverts the failed turn so you don't have to throw away the session (you can /unrevert it). It's a stopgap until opencode fixes it upstream. The approaches are from #8497 and #1662.

    If your error turns out to be something else (like a tool-argument validation failure), ignore me, this one's only for the tool_use/tool_result pairing error.

  16. github-actions commented on Aug 29, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

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