Skip to content

fix(opencode): fail runs when the model stream ends without a finish frame - #40032

Closed
zhang17-24 wants to merge 1 commit into
anomalyco:devfrom
zhang17-24:fix/39968-truncated-stream-finish-error
Closed

fix(opencode): fail runs when the model stream ends without a finish frame#40032
zhang17-24 wants to merge 1 commit into
anomalyco:devfrom
zhang17-24:fix/39968-truncated-stream-finish-error

Conversation

@zhang17-24

Copy link
Copy Markdown

Summary

An upstream SSE connection cut mid-turn (EOF with no finish frame, no error event) made the AI SDK emit a synthesized finish-step with finishReason "other"/undefined. opencode mapped that to the benign "unknown" finish, persisted the truncated output as a completed turn, and opencode run exited 0 — silently accepting partial generations as success (issue #39968).

Changes

  • packages/opencode/src/session/llm/ai-sdk.ts: "other"/undefined finish reasons now map to "error" instead of "unknown", matching the native runtime's semantics.
  • packages/opencode/src/session/processor.ts: a step-finish with reason "error" fails the turn, publishing a session error so opencode run exits non-zero.
  • packages/opencode/test/cli/run/run-process.test.ts: updated the two tests that pinned the exit-0 behavior — an interrupted stream now preserves partial output but exits non-zero.
  • packages/opencode/test/session/llm.test.ts: updated the adapter expectations.

Test plan

  • bun test test/cli/run/run-process.test.ts — 13 pass
  • bun test test/session/llm.test.ts — 28 pass
  • bun run typecheck in packages/opencode — pass
  • biome check — clean

Human note

I am a 19-year-old independent full-stack developer. I reviewed the full diff and confirmed the change: a model stream that ends without a finish frame now fails the run instead of exiting 0 with truncated output.

Fixes #39968

…frame

An upstream SSE connection cut mid-turn (EOF with no finish frame, no error
event) made the AI SDK emit a synthesized finish-step with finishReason
"other"/undefined. opencode mapped that to the benign "unknown" finish,
persisted the truncated output as a completed turn, and `opencode run`
exited 0 — silently accepting partial generations as success (issue anomalyco#39968).

- ai-sdk adapter now maps "other"/undefined finish reasons to "error"
  instead of "unknown", matching the native runtime's semantics
- the session processor fails the turn on an "error" step-finish, publishing
  a session error so `opencode run` exits non-zero
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential related PRs found:

  1. fix(opencode): make long-lived provider streams robust to silent SSE terminations #39970 - fix(opencode): make long-lived provider streams robust to silent SSE terminations

    • Directly related to the same issue domain (silent SSE terminations causing stream failures)
  2. fix: retry truncated provider streams #39473 - fix: retry truncated provider streams

  3. fix(session): retry empty stream truncations and discard partial parts #26167 - fix(session): retry empty stream truncations and discard partial parts

    • Historical PR addressing similar stream truncation handling

These PRs appear to be related to the same problem space of handling incomplete/truncated provider streams. PR #39970 in particular seems highly relevant as it also deals with "silent SSE terminations" which is the exact scenario described in #40032 (EOF with no finish frame).

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Aug 1, 2026
@github-actions github-actions Bot closed this Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Silent SSE terminations: EOF without a finish frame completes the turn, chunkTimeout misses stalled streams, provider error bodies are discarded

1 participant