Skip to content

fix(opencode): tolerate orphan reasoning/text stream-state parts - #39134

Closed
DragonBaiMo wants to merge 1 commit into
anomalyco:devfrom
DragonBaiMo:tolerate-orphan-stream-parts
Closed

fix(opencode): tolerate orphan reasoning/text stream-state parts#39134
DragonBaiMo wants to merge 1 commit into
anomalyco:devfrom
DragonBaiMo:tolerate-orphan-stream-parts

Conversation

@DragonBaiMo

Copy link
Copy Markdown

Problem

Sessions using reasoning-capable models behind OpenAI-compatible / Anthropic proxies repeatedly fail with:

ERROR message=process error="reasoning part 0 not found" stack=undefined

Each occurrence aborts the assistant turn. In one local log this fired ~1500 times across multiple sessions, making such proxies effectively unusable.

Root cause

The Vercel AI SDK's streamText reasoning/text state machine enqueues a non-fatal in-band error part when a reasoning-delta / text-delta (or its -end) arrives with no preceding reasoning-start / text-start block:

{ type: "error", error: `reasoning part ${id} not found` } // or `text part ${id} not found`

(packages/ai/src/generate-text/stream-text.ts — text part L1171/L1190, reasoning part L1220/L1239). The SDK returns and keeps streaming, i.e. it treats this as recoverable bookkeeping. Proxies that stream thinking deltas without emitting the start block trigger it constantly.

opencode's AI SDK adapter promoted everyerror part to a fatal Effect.fail:

case"error":
returnEffect.fail(event.error)

which SessionProcessor.halt() logs (stack=undefined, because the payload is a plain string) and turns into an aborted turn + Session.Event.Error.

Note that opencode already tolerates the same orphan condition on the delta path (session/processor.ts: "silently drop orphan deltas (no preceding reasoning-start)"). The SDK-internal error part simply took a different code path that bypassed that existing tolerance.

Fix

Recognize these narrow, SDK-internal orphan stream-state errors in the adapter (session/llm/ai-sdk.ts) and drop them (debug log, no emitted events) instead of failing the turn. Matching is intentionally strict — prefix reasoning part / text part plus suffix not found — so genuine provider errors (rate limits, Tool "x" not found, etc.) still fail as before. If the SDK ever changes the wording, the matcher simply stops matching and behavior reverts to the prior fatal path (fails loud, never swallows silently).

Testing

  • bun run typecheck — clean
  • bun test test/session/ai-sdk.test.ts — 3 pass / 15 assertions
    • orphan reasoning part … / text part … strings (incl. colon ids like rs_abc:0) → dropped, turn continues
    • genuine errors (rate limit exceeded, Tool "foo" not found, Error) → still fail

The AI SDK enqueues a non-fatal "reasoning part <id> not found" / "text
part <id> not found" error part when a reasoning/text delta arrives with no
preceding *-start block (common with OpenAI-compatible and Anthropic
proxies). The adapter promoted every error part to a fatal Effect.fail,
aborting the turn and spamming logs. Recognize these SDK-internal orphan
stream-state errors and drop them instead of failing; genuine errors still
fail.
@github-actionsgithub-actionsBot added the needs:compliance This means the issue will auto-close after 2 hours. label Jul 27, 2026
@github-actions

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

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

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

The search found one related PR worth noting:

Related PR:

However, this is a different fix targeting a different issue. PR #39134 (the current PR) specifically addresses orphan reasoning/text stream-state errors from the Vercel AI SDK, while PR #26167 focuses on empty stream truncations and partial parts.

No duplicate PRs found

@github-actions

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-actionsgithub-actionsBot removed the needs:compliance This means the issue will auto-close after 2 hours. label Jul 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DragonBaiMo