anomalyco / anomalyco/opencode
Image-count 400s (Azure: "Exceeded maximum number of images (50)") are not classified as context overflow, so media-strip compaction never triggers
@rekram1-node is already working on this.
Since Jul 30, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
Azure OpenAI hard-caps requests at 50 images. In long agentic sessions where the model reads many images (screenshots, render stills), the full-history resend eventually crosses that cap and every subsequent turn fails with a fatal 400. opencode already ships an auto-recovery designed for exactly this situation — compact, strip media from context, retry — but it never triggers here, because the error is not classified as context_overflow.
Environment
- opencode 1.18.5
- model
openai/gpt-5.6-terravia OpenRouter, routed to the Azure upstream
What happens
A session accumulated 47 image read tool results; the next user turn attached 4 more images and failed with:
{"error":{"message":"Provider returned error","code":400,"metadata":{"raw":"{\n \"error\": {\n \"message\": \"Exceeded maximum number of images (50) allowed in the request.\",\n \"type\": \"invalid_request_error\",\n \"param\": \"input\",\n \"code\": null\n }\n}","provider_name":"Azure","is_byok":false}}}
The turn surfaces as a plain non-retryable api_error. Because the oversized history is resent on every turn, the session is permanently poisoned from this point — no retry can succeed, only compaction/media-stripping could.
Root cause
parseAPICallError (packages/opencode/src/provider/error.ts) classifies an error as context_overflow only when one of these holds:
isContextOverflow(message)matches (packages/llm/src/provider-error.ts) — the pattern list is entirely token/length phrases (prompt is too long,context_length_exceeded,too many tokens, …),- HTTP status is 413,
body.error.code === "context_length_exceeded".
Azure's image-count error matches none of them: it is a 400 (not 413), the inner code is null (and OpenRouter's wrapper reports numeric code: 400), and no pattern mentions images.
When classification does return context_overflow, SessionCompaction runs with overflow: true, which compacts, strips media from context, and auto-continues with "The previous request exceeded the provider's size limit due to large media attachments…" (packages/opencode/src/session/compaction.ts) — exactly the right remedy for this failure.
Suggested fix
Add an image-count pattern to patterns in packages/llm/src/provider-error.ts:
/maximum number of images/i,
message() appends the raw response body, so the pattern matches even through OpenRouter's double-wrapped payload (the Azure message is nested as an escaped string inside metadata.raw). Other providers have similar per-request media-count caps; the Azure 50-image message is the one observed in the wild.
Repro sketch
- Run a session on an Azure-served OpenAI model (directly, or via OpenRouter with
provider.order: ["azure"]). - Have the agent
read50+ images across turns (or attach them as file parts). - The next turn fails with the fatal 400 above instead of compacting with media-strip and continuing.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.