Repository navigation
Description
Observed defect: sessions stall in a loop of ~4-token no-message completions (claude-sonnet-5-5 via claude-code provider)
Observed twice on 2026-11-06 evening (CST), production server (fork build 08eca39), during the fleet feature wave on issue #1885:
- Session
ses_e5e4c6d3d7dffegQw6FgFK7K2u(routespecialist, providerclaude-code, modelclaude-sonnet-5-5, variant high): after ~40 productive minutes it began emitting route attempts withtokens_output = 4,assistant_message_id = NULL, outcomesuccess, recurring roughly every ~4 minutes (route_attempt ids 323432, 323500; tokens_input ~110k). No new session messages, no tool calls; a minder "Continue." prompt was accepted (HTTP 200) and also produced only a 4-token no-message attempt. Session was interrupted by the minder. - Successor session
ses_e5e4c5f4065ffeGMJc7943Q5sG(same route/model, fresh context, ~50k input tokens): three productive attempts, then the same 4-token no-message pattern and stall. Interrupted by the minder. - Control group: two sessions on the
workhorseroute (DeepSeek) ran 60+ minutes the same evening with no such stall; the feat: API launch mode that disables thequestiontool entirely for detached / non-interactive sessions #1885 stream was relaunched on workhorse and proceeded normally.
Why it matters: a session in this state looks merely quiet — it burns a full-context attempt every few minutes and never progresses, and the retry/continuation machinery does not surface it as an error (outcome is recorded as success). It is adjacent to #1891 (serving-leaf invisibility) but distinct: the failure is in the attempt loop, not observability.
Suggested investigation: what a 4-token completion with no assistant message contains (stop reason?), why the loop keeps scheduling continuations after empty completions, and whether an empty-completion streak should trip the availability/cascade machinery (treat N consecutive no-message completions as a failed attempt and fail over).
Evidence: route_attempt rows for the two sessions above in the laptop server store (~/.local/share/opencode/opencode.db), 2026-11-07T00:50Z–01:45Z.
Acceptance criteria
- A claude-code-provider session that receives a no-message ~4-token completion does not loop indefinitely: the loop is detected (repeated no-message completions) and the session surfaces an error or recovers instead of silently stalling
- Route-attempt records for the stall pattern are distinguishable from genuine short completions (a marker, outcome, or message-id invariant is enforced or logged)
- Regression coverage reproduces the observed pattern (successive 4-token, NULL-message attempts) against the session loop
Activity
developing-today commentedon Nov 7, 2026
Triage evidence — CONFIRMED by reading current main (issue-sweep-rotating)
Checked 2026-11-07T05:45Z against main
cfc5e3d82cd2e9c0d6e304cdc6644218f26d8905(freshgh apiraw reads, verified twice). No local repro run in this feeder pass — the production evidence is the two session IDs androute_attemptrows named on the issue (laptop server store, 2026-11-07T00:50Z–01:45Z); the code read below shows why that pattern is possible and invisible:packages/core/src/session/runner/step.ts:584-590— the attempt row'soutcomeis"interrupted"/"timeout"/"failure"only when the stream interrupted, timed out, failed, or hit a policy finish; every other completion — including one that produced no assistant message — falls through to"success".tokens_outputis recorded verbatim (step.ts:607), so a 4-token no-message attempt is indistinguishable from a productive one in outcome terms.emptyoverpackages/core/src/session/runner/step.ts,runner/retry.ts, andrunner/llm.tson current main: zero matches in all three files (verified twice). Nothing counts consecutive no-message completions, nothing treats an empty streak as a failed attempt, and the failover/cascade gate (step.ts:692) keys only onllmFailure— which a "successful" empty completion never sets.What "done" looks like (from the issue, made testable): N consecutive no-message completions for a session are treated as a failed attempt (failover/cascade engages, or the turn ends with a visible error) instead of an unbounded series of
successrows; a single empty completion followed by a productive one does not trip it. Tests name their oracle: a scripted provider returning empty completions — assert attempt outcomes and that the loop terminates.Enqueued as a triage packet to the pilot queue by this feeder (see the agent note that follows).
developing-today commentedon Nov 7, 2026
Enqueued by
issue-sweep-rotating(triage feeder) as queue task 11037 (repo-health-opencode-pilot, kindtriage, priority 70, deduperepo-health:v1:triage:developing-today/opencode:issue:1903). Triage evidence is in the comment above (6702970740): a no-message completion recordsoutcome=successatrunner/step.ts:584-590, and no empty-completion guard exists in the runner (grepempty= 0 in step/retry/llm). Thequeue/queuedlabel is applied in the same pass.dezren39 commentedon Nov 7, 2026
Intake review
Related: filed from the 2026-11-06 feature wave on issue #1885, where two sessions stalled and a minder 'Continue.' prompt did not break the loop; the DeepSeek workhorse control group ran 60+ minutes clean, which points at the claude-code provider path rather than the session machinery in general. Risks: a blunt retry cap could kill legitimately terse completions — detection should key on the no-message property, not token count alone. Suggested approach: instrument the attempt loop for consecutive no-message completions, then decide between provider-level retry-with-backoff and session-level escalation using the recorded attempt ids in the issue.
— Fleet monitor intake (repo-fleet-monitor, 2026-11-07 run): acceptance criteria appended to the issue body, labels normalized (kind/bug, source/human, priority/high, effort/m, status/needs-triage, meta/enriched), marked meta/enriched. No merged PR or commit was found this run that explicitly resolves this issue, so it stays open.
dezren39 commentedon Nov 9, 2026
Claimed queue task 11037 on lane 3fe37e8a-c61b-419c-9e97-769ecd264d5d. Fresh GitHub check: issue #1903 is open, no matching PR exists, and no hard-stop labels are present. Validating packet consistency before any code work.
dezren39 commentedon Nov 9, 2026
Queue task 11037 was blocked as packet_defect after fresh verification. The packet is labeled
kind=triageand says triage is confirmed, but its acceptance criteria and scope require implementation of the empty-completion guard plus regression tests. No code or worktree was created. Please correct/re-enqueue this as an implementation task; the queue claim is released.