You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
V2 TUI silently succeeds on empty length turns until manual compaction #52015
In OpenCode v2.0.18's TUI, a long session stopped answering despite accepting prompts. Four consecutive assistant turns were stored with finish: "length", tokens.output: 0, and empty assistant content. Each was followed by an idle outcome of succeeded; the TUI showed no error. Manually running compaction made the session work again.
The model used an OpenAI-compatible provider and was configured for 1,050,000 context tokens and 128,000 output tokens. Input including cache rose from 921,222 to 921,238 tokens while reasoning fell from 344 to 328; input plus reasoning stayed at 921,566 for all four turns. No automatic compaction was recorded. This is consistent with context pressure, though the source of the effective cap is unconfirmed.
Expected: automatic recovery when safe, or a visible truncation error. An empty turn should not be marked successful. Related reports: #44609, #50949, and #37372; this report adds a v2.0.18 TUI reproduction and manual-compaction recovery.
Plugins
No plugin tool call occurred in the failing turns.
OpenCode version
v2.0.18
Steps to reproduce
Use a reasoning model with a long, tool-heavy TUI session until input including cache is about 921,000 tokens under the limits above.
Submit a normal request, then short follow-ups. The model runs, but no answer or error appears.
Manually compact the session. Responses work again.
This is #50949 (already flagged as the duplicate). A fix is open in #51741.
The change: a normalized length finish with no streamed output now fails the Step with a visible error instead of settling as a success, so an empty turn stops looking like a healthy one. Partial output is unaffected - a length finish that streamed any content still settles normally with its visible text - and a length finish with tool calls still continues.
Your detail that manual compaction recovers the session is consistent with the same code path: nothing marks the empty turn as failed, so there is no reason to surface an error or recover automatically. #51741 makes the failure visible; it does not add automatic recovery, which is the separate ask tracked in #44609.
Thanks for the detailed report. I reproduced this with a simulated model whose responses always finish with reason length and contain no text, reasoning or tool calls.
v2.0.18: each prompt produces one assistant message with finish: "length", empty content and 0 output tokens. The session goes idle, and the TUI shows no answer and no error. No automatic compaction is attempted.
Latest dev (86ce19d96): the output-limit continuation added in feat(core): continue responses after output token limits #53876 runs, so each prompt now produces three empty length turns. The TUI still shows no error, and compaction still isn't attempted.
The recording below shows the v2.0.18 run, and the screenshot shows the empty turns on dev. The script below reproduces it.
Related work: open PRs #56673 and #51741 both handle turns that finish with no output, and #44609 proposed compacting and retrying in this case. Until then, a manual compaction like the one you used is the workaround.
recording.mp4
Reproduction script (drive.ts)
// Reproduces #52015: a provider step that finishes with finish_reason "length"// and no content is settled as a successful, silent turn.import{Effect,Stream}from"effect"import{Llm,OpenCodeDriver}from"opencode-drive"exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true},},({ ui, llm, opencode })=>Effect.gen(function*(){letcalls=0// Every model request: empty stream, finish reason "length", no text/reasoning/tool calls.yield*llm.serve(()=>{calls++returnStream.make(Llm.finish("length"))})yield*ui.screenshot("01-home")yield*ui.submit("Summarize the project status")yield*Effect.sleep("6 seconds")yield*ui.screenshot("02-after-first-prompt")yield*ui.submit("hello?")yield*Effect.sleep("6 seconds")yield*ui.screenshot("03-after-second-prompt")yield*Effect.log(`model requests served: ${calls}`)// Dump the stored assistant messages: finish, tokens and any error.constsessions: any=yield*opencode.session.list()for(constsessionof(sessions.items??sessions.data??sessions)asany[]){constmessages: any=yield*opencode.message.list({sessionID: session.id}asany)for(constmof(messages.items??messages.data??messages)asany[])if(m.type==="assistant")yield*Effect.log(JSON.stringify({finish: m.finish,tokens: m.tokens,error: m.error,content: m.content}))}}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Activity
github-actions commentedon Sep 29, 2026
This issue might be a duplicate of existing issues. Please check:
finish_reason: "length"empty/zero-output response is treated as a successful turn with no visible error.lengthcompletion before assistant output, with compaction and retry proposed as recovery.lengthfinish with zero visible output while the session succeeds.lengthturns being recorded as normal completions, especially when no usable output was produced.Veld101 commentedon Sep 29, 2026
This is #50949 (already flagged as the duplicate). A fix is open in #51741.
The change: a normalized
lengthfinish with no streamed output now fails the Step with a visible error instead of settling as a success, so an empty turn stops looking like a healthy one. Partial output is unaffected - alengthfinish that streamed any content still settles normally with its visible text - and alengthfinish with tool calls still continues.Your detail that manual compaction recovers the session is consistent with the same code path: nothing marks the empty turn as failed, so there is no reason to surface an error or recover automatically. #51741 makes the failure visible; it does not add automatic recovery, which is the separate ask tracked in #44609.
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I reproduced this with a simulated model whose responses always finish with reason
lengthand contain no text, reasoning or tool calls.finish: "length", empty content and 0 output tokens. The session goes idle, and the TUI shows no answer and no error. No automatic compaction is attempted.dev(86ce19d96): the output-limit continuation added in feat(core): continue responses after output token limits #53876 runs, so each prompt now produces three emptylengthturns. The TUI still shows no error, and compaction still isn't attempted.The recording below shows the v2.0.18 run, and the screenshot shows the empty turns on
dev. The script below reproduces it.Related work: open PRs #56673 and #51741 both handle turns that finish with no output, and #44609 proposed compacting and retrying in this case. Until then, a manual compaction like the one you used is the workaround.
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.