Skip to content

messages.87: tool_use ids were found without tool_result blocks immediately #10616

Closed

Description

@JacquesGariepy

Description

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

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

  1. uuc110 commented on Feb 3, 2026

    @uuc110
    • 1 same issue continuously even in 1.1.40
  2. prolific commented on Feb 8, 2026

    @prolific

    Still facing this in 1.1.53

    Makes the current session completely useless. Can't continue and even with /undo it continues to show same error.
    The only solution is to start a new one which is a big waste of tokens and time.

  3. joecwu commented on Feb 8, 2026

    @joecwu

    I’ve experienced this issue with the Claude model. When I switch to Gemini, it works. It could be that some tools are incompatible with the Claude model.

  4. rekram1-node commented on Feb 8, 2026

    @rekram1-node
    Contributor

    can anyone send me a session this happened in? opencode export > session.json

  5. robertyates commented on Feb 10, 2026

    @robertyates

    i can't send the full trace due to privacy, but here is the error message

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

    when i look in the logs for that id i only get one reference which is here

    {                                                                                    
                "id": "prt_c440403b90013VHY5TQbZ0H07r",                                                                                 
                "sessionID": "ses_3bc033f4dffe4p39JbC2Ix0iRF",                                                                          
                "messageID": "msg_c4403fb2a001Wn7YPcpeY4fq7c",                                                                          
                "type": "tool",                                                                                                         
                "callID": "toolu_018SHDkB3Q3R6oyrrWzb2fje",                                                                             
                "tool": "edit",                                                                                                         
                "state": {                                                                                                              
                  "status": "error",                                                                                                    
                  "input": {},                                                                                                          
                  "error": "Tool execution aborted",                                                                                    
                  "time": {                                                                                                             
                    "start": 1770667684458,                                                                                             
                    "end": 1770667684458                                                                                                
                  }                                                                                                                     
                }                                                                                                                       
              }
    

    i am fairly confident that this was caused by parallel tool calls both trying to edit

    it looks as though opencode prevents the second edit from ever firing and so it never gets a tool response. I am still digging a little bit, but wanted to post this if it helps.

    UPDATE: this is what my coding agent says, it chewed on this for a while

    But I think I found the actual bug. Look at the tool-error handler in processor.ts:
    
    ⏺ Read 1 file (ctrl+o to expand)
    
    ⏺ Line 198: if (match && match.state.status === "running") - the tool-error handler only processes errors for tools in "running" status.
       If the SDK emits a tool-error for a tool that's still in "pending" status (because tool-call was never processed), the error is
      silently ignored. The tool stays "pending", eventually gets cleaned up as "aborted", but the SDK's proper error result is dropped.
    
      Same issue exists for tool-result at line 179: if (match && match.state.status === "running").
    
      The fix is to also handle these events for "pending" tools:
    
    ⏺ Update(~/Documents/GitHub/opencode/packages/opencode/src/session/processor.ts)
    
    ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     Edit file
     ../opencode/packages/opencode/src/session/processor.ts
    ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
     171                  }
     172                  case "tool-result": {
     173                    const match = toolcalls[value.toolCallId]
     174 -                  if (match && match.state.status === "running") {                                                                
     174 +                  if (match && (match.state.status === "running" || match.state.status === "pending")) {                          
     175 +                    const startTime =                                                                                             
     176 +                      match.state.status === "running" ? match.state.time.start : Date.now()                                      
     177                      await Session.updatePart({
     178                        ...match,
     179                        state: {
    ...
     183                          metadata: value.output.metadata,
     184                          title: value.output.title,
     185                          time: {
     184 -                          start: match.state.time.start,                                                                          
     186 +                          start: startTime,                                                                                       
     187                            end: Date.now(),
     188                          },
     189                          attachments: value.output.attachments,
    ...
     197
     198                  case "tool-error": {
     199                    const match = toolcalls[value.toolCallId]
     198 -                  if (match && match.state.status === "running") {                                                                
     200 +                  if (match && (match.state.status === "running" || match.state.status === "pending")) {                          
     201 +                    const startTime =                                                                                             
     202 +                      match.state.status === "running" ? match.state.time.start : Date.now()                                      
     203                      await Session.updatePart({
     204                        ...match,
     205                        state: {
    ...
     207                          input: value.input ?? match.state.input,
     208                          error: (value.error as any).toString(),
     209                          time: {
     206 -                          start: match.state.time.start,                                                                          
     210 +                          start: startTime,                                                                                       
     211                            end: Date.now(),
     212                          },
     213                        },
    
  6. DamianB-BitFlipper commented on Feb 15, 2026

    @DamianB-BitFlipper
    Contributor

    This happened to me on v1.2.2 using opus 4.6 (computer went asleep while the model was running, maybe related), but seems unrecoverable.

  7. TiidSizaan commented on Mar 6, 2026

    @TiidSizaan

    Additional data: quantified impact from a single user's database

    I ran a forensic analysis of my local opencode.db and found this bug is far more widespread than a single broken session. Here's the full picture from one user's installation.

    Scale of impact

    Metric Count
    Sessions affected 44
    Total orphaned tool_use parts (no tool_result) 311
    Workspaces/directories hit 18

    Tool type breakdown — it's not tool-specific

    Tool Aborted calls Origin
    write 187 OpenCode core
    apply_patch 46 OpenCode core
    task 33 Plugin (oh-my-opencode)
    bash 12 OpenCode core
    glob 10 OpenCode core
    read 4 OpenCode core
    delegate_task 4 Plugin
    background_output 4 Plugin
    todowrite 3 OpenCode core
    edit 2 OpenCode core

    The write tool alone accounts for 60% of all orphaned tool calls.

    The step-retry mechanism is the amplifier

    A single interrupted message can accumulate massive numbers of orphaned tool_use parts because each retry step creates new tool calls that also get aborted:

    Message Step-start retries Orphaned tool_use parts
    msg_bed1beb4f... (Bulk File Editing project) 125 retries 173 orphaned parts
    msg_cc05afa1... (MCP gating session) 14 retries 26 orphaned parts

    The worst single message has 125 step-starts — meaning OpenCode retried 125 times, each time creating new tool_use blocks that were never resolved with tool_results.

    Root cause chain (confirmed by DB analysis)

    1. Session interrupted (user cancel, context overflow, timeout, crash)
    2. In-flight tool calls marked "status":"error", "error":"Tool execution aborted" in the part table
    3. No corresponding tool_result message created in the message table
    4. Step-retry mechanism creates new step-start → retries the same operation → new tool_use blocks → also aborted → repeat
    5. On session resume, message reconstruction includes all orphaned tool_use blocks → Anthropic API rejects with tool_use ids were found without tool_result blocks
    6. Session permanently broken — cannot resume without manual DB surgery

    Workaround (manual DB fix)

    For anyone stuck, this SQL fixes a specific broken session:

    -- Back up first!
    -- Delete orphaned tool parts for a specific session
    DELETE FROM part 
    WHERE session_id = '<your_session_id>' 
      AND json_extract(data, '$.type') = 'tool' 
      AND json_extract(data, '$.state.error') = 'Tool execution aborted';
    
    -- Also delete the empty API error message (if present)
    DELETE FROM message 
    WHERE session_id = '<your_session_id>' 
      AND json_extract(data, '$.error.data.message') LIKE '%tool_use%ids were found without%tool_result%';

    Suggested fix location

    The fix should be in the message reconstruction path — when OpenCode builds the API message array from the database, it should either:

    1. Filter out tool parts with "error":"Tool execution aborted" that have no matching tool_result, OR
    2. Generate synthetic tool_result blocks for aborted calls (e.g., {"type":"tool_result","content":"Tool execution was aborted"})

    This is closely related to #12234 (infinite retry loop) which creates the conditions, and the step-retry mechanism in processor.ts which amplifies the damage.

  8. frouo commented on Mar 17, 2026

    @frouo

    This happened to me on v1.2.2 using opus 4.6 (computer went asleep while the model was running, maybe related), but seems unrecoverable.

    Same here ✋. Yesterday night, I launched BUILD agent on a (quite huge) plan and leave the computer while in running. On the morning I have this error; the session looks like broken. I suspect my mac went asleep while the model was running.

  9. oetr commented on Mar 20, 2026

    @oetr

    Happened to me too, in multiple different sessions, with v1.2.27 using opus 4.6.
    Resume with opus not possible, causes same error.
    I switched to gpt-5.3 codex to continue my session as a workaround.

  10. nhp commented on Mar 22, 2026

    @nhp

    The "quick & dirty" workaround from @TiidSizaan seems to work as an intermediary "solution"

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions