anomalyco / anomalyco/opencode

Assistant message hangs forever (empty parts, never completes) on text-only turns in 1.18.25 — fixed by 1.18.26

Open
#46,858 0 comments 0 reactions 1 assignee View on GitHub

@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:

  1. A message that's text-only from the start (e.g. "Say hi in exactly three words, do not use any tools").
  2. 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 opencode process; 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 the opencode-web.service journal (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}/message failing with a session_message.seq NOT 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.