Repository navigation
Description
Summary
A long-running session started failing with [missing_required_parameter] Missing required parameter: 'messages[100].reasoning_content' after a mid-session provider.updated/model.updated event. The upstream provider now requires reasoning_content for every earlier assistant message, but one message in history (index 100) has none, so every subsequent request in the session is rejected.
Environment
- opencode version: 2.0.28
- OS: Windows_NT 10.0.26200 (win32 x64)
- Terminal: TERM=xterm-256color (TERM_PROGRAM unset)
- Shell: C:\WINDOWS\system32\cmd.exe
- Install/channel: release (latest)
- Active plugins: none found in config (only an MCP server
blender-mcpconfigured)
Reproduction
- Start a build session on a reasoning model from the
opencodeprovider (session was at ~100 messages). - Let a tool call get interrupted mid-turn (a
Start-Sleepforeground shell command hit the 120s tool timeout and was interrupted). - Shortly after, an automatic
provider.updated+model.updatedevent fires (polling refresh, every ~5 min in this log). - The next continuation request fails with the error below; retries fail the same way.
Expected Behavior
Session continues normally; either OpenCode preserves/replays reasoning_content for prior assistant messages, or it strips/normalizes history to match the active model's requirements.
Actual Behavior
Two consecutive errors in the log, then the session was only usable again after a later provider/model refresh:
timestamp=2026-10-13T09:21:43.610Z level=ERROR run=23ed6170 message="Failed to drain Session" cause="AI.Error: Upstream request failed: [missing_required_parameter] Missing required parameter: 'messages[100].reasoning_content'. This model needs the reasoning of every earlier assistant message: send back the 'reasoning_content' returned with that message."
timestamp=2026-10-13T09:21:54.968Z level=ERROR run=23ed6170 message="Failed to drain Session" (same error)
Related events right before the failure:
09:19:07 event.type=provider.updated
09:19:07 event.type=model.updated
Note: an interrupted tool call occurred at 09:19 (Tool execution interrupted for a foreground shell command), possibly leaving a truncated assistant message without reasoning content at history index 100.
Additional Context
- Frequency: twice in one session (09:21:43 and 09:21:54), triggered consistently until the session state moved past the bad message.
- Workaround: starting a new session avoids the issue.
- The session had ~100 messages, so older messages were likely written by a different model/provider revision before the refresh.
- Hypothesis: message history persisted without
reasoning_content+ a provider that strictly requires it for all earlier assistant messages = unrecoverable session. OpenCode could either persist reasoning content for reasoning models or sanitize history when the active model requires it.
Activity
opencode-agent commentedon Oct 13, 2026
Thanks for the detailed report. I was able to reproduce this on 2.0.28, and it still happens on the latest
dev(4ffede4).What I did, using a simulated OpenAI-compatible thinking model that sends reasoning back in
reasoning_content:In the request for step 3, the completed turn is sent with its
reasoning_content. The interrupted assistant message is sent with an emptyreasoning_content, and its reasoning text is moved into the normal message content. A provider that needs the reasoning of every earlier assistant message rejects that, which matches yourMissing required parameter: 'messages[N].reasoning_content'error. Because the same message is sent again on every request, the session stays broken. No provider or model switch was needed, so theprovider.updated/model.updatedevents in your log were probably a coincidence. The interrupted tool call is what triggers it.The recording and screenshot below show the run, and the script below reproduces it.
Related: #38620 is the same underlying behaviour hitting Anthropic thinking, and #54693 is an open PR in this area. Starting a new session remains the workaround for now.
recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.JonnieDoe commentedon Nov 3, 2026
Same error on v2.2.5 (macOS 27.2.0 arm64, tmux/zsh, channel: latest), this time at
messages[20]:Provider: custom OpenAI-compatible endpoint (reflection.ai, via @ai-sdk/openai-compatible), model Beam-1.0-501B-A23B — a thinking model served with DeepSeek-style reasoning_content semantics.
Context:
opencode-agent commentedon Nov 13, 2026
@CTKiet2006 @JonnieDoe thanks both, and sorry this bricks the session.
Workaround: tell OpenCode the model needs
reasoning_contentsent back on every earlier assistant message. Add acompatibilityblock to the model inopencode.jsonc:@CTKiet2006 (built-in
opencodeprovider). Put in the model ID you were using:{ "providers": { "opencode": { "models": { "<model-id>": { "compatibility": { "reasoningField": "reasoning_content", "requireReasoning": true } } } } } }@JonnieDoe (custom reflection.ai endpoint). Add it to the model you already have, or to the provider so it covers every model there:
{ "providers": { "reflection": { "package": "@ai-sdk/openai-compatible", // ...your existing settings "models": { "Beam-1.0-501B-A23B": { "compatibility": { "reasoningField": "reasoning_content", "requireReasoning": true } } } } } }With this set, OpenCode always sends
reasoning_contenton earlier assistant messages, even ones that have no reasoning stored.If it still fails after that, please send:
opencode export <sessionID>) or just the assistant message at the failing index, with anything sensitive removed. We mainly want to know whether that message has a reasoning part and whether it was the interrupted turn.@tarquinen/opencode-dcp, since it prunes context and could strip reasoning from old messages. Also the message atmessages[20]if it happens again."reasoning_content": ""(an empty string) on that message or no field at all. That tells us whether the provider rejects an empty value, which decides the fix on our side.