Repository navigation
Description
Environment
- opencode version: 1.17.20 (TUI & Desktop)
- Models confirmed affected: deepseek-v4-pro, deepseek-v4-flash, glm-5.2, qwen3.6-plus-free (see Frequency table for sample sizes)
- OS: Debian 13 (Linux 6.12.95) and Windows 11 (10.0.26200) — both confirmed
- Terminal: SSH xterm-256color (Linux) / opencode Desktop (Windows)
Description
After a +Thought block completes, the final response text sometimes does not render at all. The TUI shows only the Thought block content and then the mode indicator (e.g. ▣ Plan · DeepSeek V4 Pro · 43.2s or ▣ Build · DeepSeek V4 Pro · 12.4s) with no summary text below it.
Database inspection confirms: the buggy turn has a reasoning part but no text part at all — the text part was never created. The text-start event appears to have never fired, so processor.ts never instantiated a TextPart.
Screenshot: see comments.
Steps to Reproduce
- Start opencode in TUI or Desktop mode
- Use a reasoning model (DeepSeek V4 Pro confirmed most affected) with thinking mode enabled
- Have a multi-turn conversation (the bug tends to appear after context accumulates — first observed occurrence ranged from turn 15 to turn 304 in different sessions)
- Some turns end with only the Thought block — no summary text is rendered after it
Frequency
Bug rate varies significantly by model, provider, and platform. Cross-platform data (Debian 13: 2 sessions, Windows 11: 70 sessions, 1211+ turns):
| Platform | Provider | Model | Mode | Turns | Bugs | Bug rate |
|---|---|---|---|---|---|---|
| Debian 13 | opencode-go | deepseek-v4-pro | build | 27 | 9 | 33.3% |
| Debian 13 | opencode-go | deepseek-v4-pro | plan | 50 | 5 | 10.0% |
| Debian 13 | opencode-go | deepseek-v4-flash | build | 261 | 1 | 0.38% |
| Debian 13 | opencode-go | glm-5.2 | build | 15 | 1 | 6.7% (small sample) |
| Windows 11 | opencode-go | deepseek-v4-pro | build | 96 | 0 | 0.00% |
| Windows 11 | opencode-go | deepseek-v4-flash | build | 501 | 1 | 0.20% |
| Windows 11 | deepseek (direct) | deepseek-v4-pro | build | 105 | 5 | 4.76% |
| Windows 11 | opencode | qwen3.6-plus-free | build | 8 | 2 | 25.0% (small sample) |
Key observations:
- DeepSeek V4 Pro is the most affected model (up to 33.3% in Debian opencode-go+Pro+build); Flash is nearly immune (<0.4%)
- Not limited to DeepSeek: GLM-5.2 and Qwen3.6-plus-free also triggered the bug (though with small sample sizes — noted as inconclusive)
- All bug turns share:
finish=stop+ areasoningpart + notextpart - Platform discrepancy for opencode-go+Pro: Debian 33.3% vs Windows 0% — same provider, same model, same opencode version (1.17.20). Root cause of the discrepancy is unknown (could be proxy routing, backend version, or other factors — not investigated)
- The bug tends to appear after conversation context accumulates; it was not triggered in fresh short test sessions during reproduction attempts
Detection Method
Bug turns can be detected via SQLite query on opencode.db. The correct unit is the last assistant message of each turn (finish=stop with no later assistant message sharing the same parentID), not every intermediate message (intermediate reasoning → tool → step-finish sequences are normal tool-call steps, not bugs).
SELECT
json_extract(m.data,$.providerID) as provider,
json_extract(m.data,$.modelID) as model_id,
json_extract(m.data,$.agent) as mode,
CASE WHEN EXISTS (SELECT 1 FROM part p
WHERE p.message_id=m.id AND json_extract(p.data,$.type)='text')
THEN 'ok' ELSE 'bug' END as ending,
COUNT(*) as turn_count
FROM message m
WHERE json_extract(m.data,$.role)='assistant'
AND json_extract(m.data,$.finish)='stop'
AND json_extract(m.data,$.parentID) IS NOT NULL
AND EXISTS (SELECT 1 FROM part p WHERE p.message_id=m.id AND json_extract(p.data,$.type)='reasoning')
AND NOT EXISTS (
SELECT 1 FROM message m2
WHERE json_extract(m2.data,$.parentID) = json_extract(m.data,$.parentID)
AND m2.session_id = m.session_id
AND m2.time_created > m.time_created
AND json_extract(m2.data,$.role)='assistant')
GROUP BY 1, 2, 3, 4
ORDER BY 1, 2, 3, 4;Root Cause Analysis
Source code review + database inspection findings:
-
Not a TUI rendering bug: The
textpart is entirely absent from the database (0 empty text parts found in buggy sessions — thetextpart was never created, not created-empty-then-hidden). The TUI<Show when={props.part.text.trim()}>inTextPartcorrectly renders nothing because there is nothing to render. -
Not a
processor.tslogic bug:processor.tscreates aTextPartimmediately ontext-start(yield* session.updatePart(ctx.currentText)at line 496). Iftext-starthad fired, atextpart would exist in the DB. Its absence meanstext-startnever fired. -
The
text-startevent never fired: Tracing upstream —ai-sdk.tsemitstext-startonly when the AI SDK receives a non-nullcontentdelta from the provider response stream. If the provider response contained nocontentfield (onlyreasoning_content), notext-startis emitted. -
Smoking gun evidence: Multiple buggy turns have
reasoningcontent ending with a complete summary sentence (e.g."简单说:配置、数据、日志全都沿用了原来的,和删除前的状态一致。"or"所以两平台的原始数据都可靠,issue 内容也是准确的,不需要重新检查。"), but notextpart was emitted. The model appears to have written its full reply insidereasoning_contentbut did not emit it ascontent. -
Most likely root cause (not yet directly verified): The model, in
finish=stopturns, sometimes outputs onlyreasoning_contentwithout acontentfield. This could be model behavior, AI SDK stream parsing, or provider proxy behavior — the exact layer was not isolated because capturing raw API responses from the Bun-compiled opencode binary was not feasible with available tooling.
See the latest comment for the cross-platform verification details.
Activity
Start-Gao commentedon Jul 15, 2026
[-]TUI: Plan mode - final response missing after +Thought block (DeepSeek V4 Pro)[/-][+]Bug report:TUI: Plan mode - final response missing after +Thought block (DeepSeek V4 Pro)[/+]Start-Gao commentedon Jul 15, 2026
Cross-platform verification & root cause analysis
Detection methodology
The correct unit for counting this bug is the last assistant message of each turn (the
finish=stopmessage with no later assistant message sharing the sameparentID). Counting every intermediatereasoning → tool → step-finishmessage as a bug is wrong — those are normal tool-call steps where the model is still working and should not yet produce summary text.Field names matter: message-level model info is in
$.modelIDand$.providerID(not$.model).Cross-platform bug rates
Debian 13 (2 sessions) + Windows 11 (70 sessions), 1211+ turns total:
Source code review findings
processor.ts(line 486-496): Ontext-start, aTextPartwith empty text is created and immediately published viasession.updatePart(). Iftext-starthad fired, atextpart (possibly empty) would exist in the database.reasoningparts but notextpart at all — not an empty one, none. This meanstext-startnever fired.ai-sdk.ts(line 126-135):text-startis emitted only when the AI SDK receives a non-nullcontentdelta from the provider stream. Nocontentdelta → notext-start→ noTextPart.TextPartcomponent (session/index.tsx:1679):<Show when={props.part.text.trim()}>correctly hides empty text. This is not the bug — there is simply no text part to render.Smoking gun evidence
Multiple buggy turns have
reasoningcontent that ends with a complete summary sentence, but notextpart was emitted:"...所以两平台的原始数据都可靠,issue 内容也是准确的,不需要重新检查。""...简单说:配置、数据、日志全都沿用了原来的,和删除前的状态一致。""...commit→rebase→push→PR 刷新流程总结"The model wrote its full reply inside
reasoning_contentbut did not emit it ascontent.What is confirmed vs. what is not
Confirmed:
textpart is entirely absent —text-startnever firedprocessor.tsand TUI rendering logic are correctNot confirmed (would need raw API response capture):
contentfield, or the AI SDK drops it, or a proxy alters itCapturing raw API responses from the Bun-compiled opencode binary was attempted via
NODE_OPTIONS=--requirefetch hook, but the Bun binary does not honorNODE_OPTIONS. A plugin-based approach is possible but was out of scope for this report.[-]Bug report:TUI: Plan mode - final response missing after +Thought block (DeepSeek V4 Pro)[/-][+]Bug report:TUI - final response missing after +Thought block (DeepSeek V4 Pro & Flash, Plan & Build mode)[/+][-]Bug report:TUI - final response missing after +Thought block (DeepSeek V4 Pro & Flash, Plan & Build mode)[/-][+]Bug report:TUI - final response missing after +Thought block (all reasoning models: DeepSeek/GLM/Qwen, Plan & Build mode)[/+]github-actions commentedon Sep 14, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.