anomalyco / anomalyco/opencode
Assistant message hangs forever (empty parts, never completes) on text-only turns in 1.18.25 — fixed by 1.18.26
@jlongster is already working on this.
Since Sep 2, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Note: this issue was filed by an AI agent (Claude, Anthropic) operating on my behalf/under my account. I reviewed the repro before posting. — Tyler
Summary
On a self-hosted opencode web (v1.18.25), any assistant turn that ends in a text-only response with no tool call never completes: the assistant message record is created immediately, but parts stays a permanent empty array and time.completed is never set. The POST /session/{sessionID}/message HTTP response itself never returns (client times out waiting), consistent with that endpoint streaming/waiting for the full turn before closing.
This affects two cases identically:
- A message that's text-only from the start (e.g. "Say hi in exactly three words, do not use any tools").
- The automatic follow-up continuation message OpenCode creates after a tool call completes, when the model needs to give its final natural-language reply. The tool-call turn itself completes fine (
finish: "tool-calls", real timestamp) — it's specifically the next message (final text reply) that hangs.
Since nearly every real conversation eventually needs a plain-text final reply, this makes 1.18.25 effectively broken for interactive use once you hit that path.
Repro steps (isolated via direct HTTP API calls, no TUI/web client involved)
POST /project/git/init?directory=/tmp/scratch # register a throwaway repo
POST /session?directory=/tmp/scratch # create a fresh session
POST /session/{sessionID}/message?directory=/tmp/scratch
{"parts":[{"type":"text","text":"Say hi in exactly three words. Do not use any tools."}]}
Result: assistant message created, parts: [], no time.completed, forever (confirmed hung 40+ seconds repeatedly, would presumably hang indefinitely). GET /session/{sessionID}/message shows the same stuck record afterward.
Isolation performed to rule out other causes:
- Not provider/model-specific — reproduced identically against both
openrouter/qwen/qwen3.8-flash(OpenRouter, cloud) and a local OpenAI-compatible provider (@ai-sdk/openai-compatible→ local llama.cpp backend). The local backend itself was verified healthy/fast (0.58s) via a direct request bypassing OpenCode entirely. - Not a concurrency issue — reproduces on a single, non-concurrent, brand-new session with no other sessions active.
- Not a long-uptime/resource-leak issue — reproduces immediately (within ~1 minute) on a freshly restarted
opencodeprocess; a full service restart did not fix it. - Fixed by upgrading to 1.18.26 — same exact repro steps against 1.18.26 completed normally (~4-5s, real text response,
finish: "stop"), for both the text-only-from-start case and the tool-call-then-text-continuation case.
Versions
- Broken: 1.18.25
- Fixed (confirmed via retest): 1.18.26
Possibly related
Found via search, not confirmed duplicates — filing this separately since none describe this exact signature (immediate, provider-agnostic, reproducible on a fresh single session, specific to the text-only/no-tool-call completion path):
- #26220 — session processor allegedly fails to detect
finish_reason=stop/text-only response as "done," same failure family (model finishes, orchestrator doesn't recognize completion) but described as an infinite-loop/CPU-spin symptom on older versions, not a permanent zero-parts hang. - #17982 — prompt loop continues after
finish=stop, different provider/context. - #28492 —
MaxListenersExceededWarning after web interface starts— we independently observed this exact warning in theopencode-web.servicejournal (inside the Effect-TS async fiber scheduler), unclear if causally related to this hang but flagging the overlap. - #16220 — cancelling mid-response leaves an assistant message with permanently empty content — same "empty-parts assistant message" symptom family, different trigger (cancellation vs. a clean fresh turn).
- #31412 —
POST /session/{id}/messagefailing with asession_message.seqNOT NULL constraint at v1.15.13 — different error mode, but shows this endpoint has had recurring fragility across versions.
Given the fix already landed by 1.18.26, this is filed mainly so the exact repro/isolation is on record in case it resurfaces, and in case it's useful context for whatever fixed it between .25 and .26 (the 1.18.26 changelog entries didn't obviously describe this fix, so it may have been an incidental side effect of another change).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.