fix(opencode): classify OpenRouter's typeless 502 overflow chunk as ContextOverflowError

Merged
PI
2mo ago
+29-6

Description

Fixes USE-2673.

When the model's context fills up behind OpenRouter, OpenRouter does not fail the HTTP request. It relays the upstream overflow as a mid-stream chunk with no type field:

{ "code": 502, "message": "Your input exceeds the context window of this model. Please adjust your input and try again.", "metadata": { "error_type": "provider_unavailable" } }

parseStreamError gated everything on body.type === "error", so this chunk returned undefined, fromError fell through to UnknownError with the JSON stringified into message, and the processor treated the turn as a generic failure. Users saw "Something went wrong" with a Retry button that re-sent the same oversized prompt: prod shows ten identical failures in three minutes for one session.

The overflow text patterns in @opencode-ai/llm already match this message, but only ran on the APICallError branch. This PR checks the message text (at error.message or top-level message) against those patterns before the type gate, and folds the existing context_length_exceeded case into the same check so overflow is classified in one place.

Now the chunk becomes ContextOverflowError, which the processor already handles: it flags needsCompaction, compacts once, and replays the prompt (converging per #41) instead of surfacing an opaque error.

Shipping this to the fleet needs a fork release tag and an OPENCODE_VERSION bump in apps/daytona-snapshot/Dockerfile in andytown.

Testing

TODO

🤖 Generated with Claude Code


Summary by cubic

Fixes OpenRouter's typeless 502 overflow chunks showing up as a generic "Something went wrong" error. These chunks now classify as ContextOverflowError, so the existing compaction and prompt-replay path runs instead of a Retry that re-sends the oversized prompt.

  • parseStreamError no longer requires body.type === "error" to match overflow message text; the context_length_exceeded code check is folded into the same pre-gate match.
  • Adds a regression test for the typeless chunk shape.
  • Shipping needs a fork release tag and an OPENCODE_VERSION bump in apps/daytona-snapshot/Dockerfile.