Skip to content

Invalid-tool fallback persists callID:"" for empty-id tool calls → every later request 400s, session permanently bricked #53499

Closed as not planned

Description

@ASIT-KuHaku

Description

When a model streams a tool call with an empty id, opencode's invalid-tool fallback
writes the part as tool:"invalid" but leaves callID:"". From then on the session is
dead: every request replays that part and the provider rejects the body before the model
runs — retrying, clicking continue, even switching models all fail identically:

400 messages[25]: tool messages must include a non-empty string tool_call_id
   (Error from provider (Console): Upstream request failed)
500 Cannot resolve tool name for tool_call_id=''. Either 'tool_calls[].function.name'
   in assistant message or 'name' in tool message must be provided.

There is no UI path to remove that one message, and the request builder doesn't sanitize
empty ids, so the session cannot self-heal.

The persisted part (opencode.db, tables part + mirrored event):

{"type":"tool","tool":"invalid","callID":"",
 "state":{"status":"completed",
   "input":{"tool":"","error":"Model tried to call unavailable tool ''. Available tools: bash, edit, ..."},
   "output":"The arguments provided to the tool are invalid: ..."}}

Stream side (mimo-v2.6-flash): every tool-call-delta chunk arrived with id: "" and no
name — only argumentsDelta — and the model also re-emitted the same call as literal
text. Same signature as #36299 and #52700.

Expected:

  1. Ingest: empty/missing id → synthesize call_<random> before persisting. The
    missing-name side already routes to the invalid tool; the id just slips through.
  2. Request build: skip/repair parts with an empty callID when assembling messages, so
    sessions that are already poisoned self-heal instead of needing manual DB surgery.

Workaround that fixed it (backup first; ran live against WAL, no restart needed):

UPDATE part  SET data=replace(data,'"callID":""','"callID":"call_<random>"')
  WHERE json_extract(data,'$.type')='tool' AND data LIKE '%"callID":""%';
UPDATE event SET data=replace(data,'"callID":""','"callID":"call_<random>"')
  WHERE data LIKE '%"callID":""%';

After the replace: 0 empty ids, PRAGMA integrity_check ok, session streamed again on
the first try.

Related: #36299 (open), #52700 (auto-closed unfixed; mimo evidence in comments),
#40235 (same family — persisted bad tool part → permanent 400s).

Plugins

none

OpenCode version

1.18.25

Steps to reproduce

  1. Long session on a model that sporadically streams tool calls with an empty id
    (mimo-v2.6-flash-free; stream-level signature documented in V2: spawning subagent failure and errors "OpenAI Chat tool call delta is missing id or name" in the UI #36299 / OpenAI Chat tool call delta is missing id or name #52700)
  2. When it happens, part table shows a tool part with tool:"invalid", callID:""
  3. Send any message in that session → 400/500 on every attempt, models don't matter

Screenshot and/or share link

(no public share — session contains local machine data; evidence pasted in Description)

Operating System

Ubuntu 22.04.2 LTS

Terminal

opencode web (browser UI) — bug is DB-level, affects TUI too

Activity

  1. github-actions commented on Oct 6, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of or closely related to existing issues. Please check:

  2. ASIT-KuHaku commented on Oct 6, 2026

    @ASIT-KuHaku
    Author

    Checked all five — none is a duplicate of this one, so keeping it open:

    Happy to consolidate under #44852 if you'd rather track all "poisoned history replay"
    cases in one place — otherwise the empty-id path seems distinct enough to track separately.

  3. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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