Repository navigation
Description
Description
A long-running OpenCode session on opencode-go/deepseek-v4.1-flash#high became permanently unusable after the agent read six PNG screenshots with the read tool during a UI-verification loop. Every later request — including bare . and Proceed — fails with:
{"error":{"param":null,"type":"invalid_request_error","code":"invalid_request_error","message":"Upstream request failed: [invalid_request_error] image input is not available on this engine (request_id: gw-add0e1b4e086-198a59)"}}The session now fails on every turn, so there is no way to continue or remove the offending image from the UI.
The model is advertised as image-capable (models.dev: opencode-go/deepseek-v4.1-flash, attachment: true, modalities.input: ["text", "image"]), and fresh probes are inconsistent: one fresh session that used read on a 1×1 PNG failed on the continuation with the same error, while an identical repeat minutes later succeeded, and a fresh session with the same PNG attached via -f also succeeded. That points to per-request backend routing in the Go gateway rather than a client-side request-shape bug.
Plugins
None. MCP servers playwright and strobe are configured; no local plugins.
OpenCode version
2.2.5 (Homebrew opencode-v2 2.2.5, official latest channel; background server, not desktop)
Steps to reproduce
- Use
opencode-go/deepseek-v4.1-flash#highon OpenCode 2.2.5. - In a session, let the agent read several PNG screenshots with the
readtool (the normal render → read PNG → adjust loop). - Continue the session normally.
- At some point every request fails with
image input is not available on this engine; new messages and retries fail identically.
Minimal intermittent reproduction:
- Create a 1×1 PNG (
pixel.png). - Run
opencode run -m opencode-go/deepseek-v4.1-flash#high --auto "Use the read tool to read pixel.png, then reply OK." - First run: the read completed, then the continuation request failed 400 with
request_id: gw-adac8a2c2d3d-19aa09. Re-running the same command minutes later succeeded, and attaching the same PNG with-fsucceeded in a fresh session.
Screenshot
Terminal/log excerpt:
2026-11-04T22:47:28.001Z ERROR ... message="Failed to drain Session" cause="AI.Error: Upstream request failed: [invalid_request_error] image input is not available on this engine (request_id: gw-add0e1b4e086-198a59)"
2026-11-04T22:47:51.904Z ERROR ... (request_id: gw-adac8a2c2d3d-198fa6)
2026-11-04T22:48:06.991Z ERROR ... (request_id: gw-adc5918ccf18-199c1a)
Operating System
macOS Darwin 25.6.0 (arm64), host servers-Mac-mini.local
Terminal
tmux (TERM=xterm-256color, TERM_PROGRAM=tmux, COLORTERM=truecolor), shell /bin/zsh
Additional context
- Session:
ses_e59822178ffeyxSx1JlIS1W8M4("Scope projects page feedback"), directory~/Development/scope, agentbuild, model{"id":"deepseek-v4.1-flash","providerID":"opencode-go","variant":"high"}. - The session contains 542 assistant messages, 9 user messages and 6 images returned by
read(messages 360, 392, 493, 747, 894, 919). Hundreds of turns succeeded after those reads; failures began when the context was at 585,728 cached input tokens. - Exact stored error body:
{"error":{"param":null,"type":"invalid_request_error","code":"invalid_request_error","message":"Upstream request failed: [invalid_request_error] image input is not available on this engine (request_id: ...)"}}. - Related: session: all history images are re-sent on every request, permanently breaking sessions on image-capped backends #59794 (history images re-sent on every request; session becomes permanently unusable), session: provider image rejection bricks session — generic 400 error, no recovery path #52042 (provider image rejection bricks a session; no recovery path), go: mimo-v2.6-flash and mimo-v2.5 advertise image input but the Go endpoint rejects every image (400) #55785 (Go endpoint rejected images for mimo models; its comments record
deepseek-v4.1-flashaccepting images on Oct 15). - Workaround for the stuck session not verified; likely a new session, a fork before the image turns, or switching to an image-capable model. The point is that a normal screenshot-verification loop can produce an unrecoverable session.
- Expected: either route image-bearing requests only to engines that accept image input and keep the published capability metadata truthful, or make the client recover when a provider rejects image content (strip/placeholder old tool-result images, retry without images, or surface a targeted recovery action). At minimum, a bare text message should not fail forever because of an old tool image.
Activity
opencodejr commentedon Nov 4, 2026
Thanks for the detailed report and the request IDs.
I couldn't reproduce this here. The error
image input is not available on this enginecomes from the OpenCode Go gateway or the upstream provider, not from the OpenCode client, and checking it needs a real OpenCode Go account, which this sandbox doesn't have. A maintainer with Go access will need to look at the gateway side, and the request IDs you included should help.As for the client, OpenCode currently re-sends every image in a session's history on each request when the model is marked as image-capable. It has no way to recover when the provider then rejects them, which is why the whole session stays stuck. That part is already tracked in:
You could try a workaround (I haven't verified it): fork or undo to before the first image turn, or switch the stuck session to another image-capable model for a turn.
Almyk commentedon Nov 4, 2026
Corroborating data from a second account/host — this is the same failure and it strongly points at per-request backend routing in the Go gateway.
Environment
2.2.5(Homebrewopencode-v2 2.2.5, official latest channel)TERM=xterm-256color,TERM_PROGRAM=ghostty,COLORTERM=truecolor), shell/bin/zshopencode-go/deepseek-v4.1-flash#maxTimeline (all 2026-11-04, UTC)
gw-adac8a2c2d3d-197d1eses_e575a23faffed23sJIdnHhFbpfgw-ad96240d07f9-1977c8ses_e575a23faffed23sJIdnHhFbpfgw-adac8a2c2d3d-19e47eses_e5731b246ffefCbp2hdRNa9D7Ogw-ad8e54dbb9ce-19e7b9ses_e5731b246ffefCbp2hdRNa9D7ONote the
gw-adac8a2c2d3dprefix is identical to the one in the report above (gw-add0e1b4e086-198a59,gw-adac8a2c2d3d-198fa6,gw-adc5918ccf18-199c1a) and the failures overlap in time — 22:44–23:04 from this host, 22:47–22:48 from yours. Two different accounts and machines hitting the same gateway node prefix in the same window suggests one (or a few) misconfigured backend deployments in the pool rather than anything client-side.A new session does not avoid it
ses_e5731b246ffefCbp2hdRNa9D7Owas created at 23:04:15 and failed on its second request at 23:04:16, so "start a fresh session" is not a workaround — that matters because it's the first thing users are told to try.Triggers and non-triggers
Trigger: a clipboard-pasted screenshot,
2000x1126JPEG, 224,856 bytes, stored as an inlinefilespart (source.type: "inline",name: "clipboard"). It was attached to a user message, not produced by thereadtool.Not a trigger on its own: content, size, or format. I extracted that exact JPEG from the failed message and re-ran it through the same provider/model/variant at 23:08–23:09 UTC — it read fine and the model described the image correctly. A 48x48 PNG also passes. So neither the image nor the request shape is the problem; the same bytes flip between working and failing depending on where the request lands.
Impact
Because the image lives in the session transcript, every subsequent step re-sends it, so the session stays unusable for as long as the bad routing persists. There is no way to drop the attachment from the UI, which matches the report above.
Happy to share a sanitized trace of either affected session if that helps pin down the routing.
ArisSwift commentedon Nov 4, 2026
Same error text, different provider — this is not only the Go gateway. Adding it as a data point for the client-side half.
Environment
2.2.5,latestchannel (Linux,x86_64, CachyOS kernel 7.3.0-4)TERM=xterm-256color,COLORTERM=truecolor, shell/bin/fishopencode/deepseek-v4.1-flash-free— note the provider isopencode, notopencode-go, and the model is the-freevariant, no#variantWhat triggered it
Not
read, and not a user attachment. An MCP tool returned an image:ai-game-developer(Unity) exposesscreenshot-game-view, which returns a PNG.Upstream request failed: [invalid_request_error] image input is not available on this engine (request_id: gw-ade77079ec61-193c07)So the third trigger shape is tool results carrying
imagecontent — the SSE/JSON path has to serialize the tool output into the next request, and the provider rejects the whole request, not just that part.This session did not brick
Worth contrasting with the reports above: the turn failed, but every following text-only request in the same session succeeded (
script-executecalls and shell tool calls ran normally for the next ~20 minutes). No retry loop, no dead session, no fork needed.That suggests the rejected image was never persisted into the transcript in this path, unlike an inline
filespart or areadresult. If so, the permanent-brick half of #52042 / #59794 is specific to image content that lands in history, and tool-result images may already be dropped on failure — which would make the client fix for that half smaller than it looks: stop the request from carrying tool-result images at all when the model has no image input, and the session never gets poisoned.Expected
Either filter
imageparts out of tool results before the request when the active model has no image input (placeholder text like "[image omitted: model has no image input]" is better than a failed turn), or reject the tool call up front with a capability error naming the model. Surfacing a raw providerinvalid_request_errorfor something the client can determine locally — the model has no image modality — is the part that costs the turn.Workaround used: verify rendered output numerically instead (
ScreenCapture.CaptureScreenshotAsTexture()+GetPixels32()in the Unity editor) and let the human look at the Game View.aitools1 commentedon Nov 4, 2026
Extra data from #61842 (same account, plain CLI, no session history), since the bot asked for it there:
Triggers without clipboard or history. Reproduced deterministically with a 426-byte PNG and
-fin a fresh session, no prior images, no MCP tool result:So an inline
filespart from a plain attachment is enough; no clipboard paste and no history re-send needed.More affected engine prefixes, none matching the
gw-adac8a2c2d3dnode above:gw-ae0e2e66bcf8,gw-add10c6ab910, plusgw-addc59e92621d,gw-addc3cc2c204,gw-adba25bd59c1from six interactive attempts between 23:25 and 23:30 UTC on 2026-11-04.Regression window. Same model, same account, images worked on:
image/pngattachments, assistant replies describe screenshot content.image/pngandimage/jpegattachments, e.g. "На скриншоте видно, что Wildberries…".First failure: 2026-11-04 23:25 UTC. No config, model or version change on my side between those dates. That bounds the regression to roughly Nov 1–4 rather than "always broken on this model".
Same account and file work on another model, so the account/key is not text-only:
opencode/nemotron-3.5-super-vl-free→ "A blue circle on a red background."Cross-checks blocked by balance:
deepseek-v4.1-flash-vision-exp→Model unavailable; paiddeepseek-v4.1-flash→Insufficient account funds.DaTurtleGuy commentedon Nov 5, 2026
Corroborating data point from a third setup, plus a possible new variant: silent image drop (no error, wrong answer).
Environment: opencode 2.0.26 CLI, headless Linux server, OpenCode Go auth, 2026-11-05 ~15:50 UTC. Fresh sessions,
-fattach of a 1x1 red PNG (RGBA 255,0,0,127, 70 bytes) — same file for all runs.opencode/deepseek-v4.1-flash-free: accepted, described correctly ("A solid red square."), 2.6s round trip. No rejection this time.opencode-go/deepseek-v4.1-flash: accepted (no 400), but answered wrong twice — "the image is a blank white square" then "White." on a red pixel. Same file the-freeroute reads correctly, so the image looks silently dropped/mangled somewhere on the Go route rather than rejected.So: no
image input is not available on this enginehit in 3 fresh runs right now (consistent with the intermittent per-request routing theory in the body), but the Go route seemingly not passing image bytes through even when it 200s. Latency was fine on all runs (~2s), for whatever that's worth as a timestamp.