Skip to content

go: deepseek-v4.1-flash image rejection bricks sessions ("image input is not available on this engine") #61827

Open

Description

@JavaGT

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

  1. Use opencode-go/deepseek-v4.1-flash#high on OpenCode 2.2.5.
  2. In a session, let the agent read several PNG screenshots with the read tool (the normal render → read PNG → adjust loop).
  3. Continue the session normally.
  4. At some point every request fails with image input is not available on this engine; new messages and retries fail identically.

Minimal intermittent reproduction:

  1. Create a 1×1 PNG (pixel.png).
  2. Run opencode run -m opencode-go/deepseek-v4.1-flash#high --auto "Use the read tool to read pixel.png, then reply OK."
  3. 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 -f succeeded 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, agent build, 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-flash accepting 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

  1. opencodejr commented on Nov 4, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report and the request IDs.

    I couldn't reproduce this here. The error image input is not available on this engine comes 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.

  2. Almyk commented on Nov 4, 2026

    @Almyk

    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

    • opencode 2.2.5 (Homebrew opencode-v2 2.2.5, official latest channel)
    • macOS Darwin 25.5.0 (arm64)
    • Ghostty (TERM=xterm-256color, TERM_PROGRAM=ghostty, COLORTERM=truecolor), shell /bin/zsh
    • No plugins configured
    • Model: opencode-go/deepseek-v4.1-flash#max

    Timeline (all 2026-11-04, UTC)

    time request_id session
    22:44:16.672 gw-adac8a2c2d3d-197d1e ses_e575a23faffed23sJIdnHhFbpf
    22:44:55.119 gw-ad96240d07f9-1977c8 ses_e575a23faffed23sJIdnHhFbpf
    23:04:16.124 gw-adac8a2c2d3d-19e47e ses_e5731b246ffefCbp2hdRNa9D7O
    23:04:39.296 gw-ad8e54dbb9ce-19e7b9 ses_e5731b246ffefCbp2hdRNa9D7O
    2026-11-04T22:44:16.672Z 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-adac8a2c2d3d-197d1e)"
    2026-11-04T23:04:16.124Z 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-adac8a2c2d3d-19e47e)"
    

    Note the gw-adac8a2c2d3d prefix 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_e5731b246ffefCbp2hdRNa9D7O was 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, 2000x1126 JPEG, 224,856 bytes, stored as an inline files part (source.type: "inline", name: "clipboard"). It was attached to a user message, not produced by the read tool.

    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.

  3. ArisSwift commented on Nov 4, 2026

    @ArisSwift

    Same error text, different provider — this is not only the Go gateway. Adding it as a data point for the client-side half.

    Environment

    • opencode 2.2.5, latest channel (Linux, x86_64, CachyOS kernel 7.3.0-4)
    • Linux, TERM=xterm-256color, COLORTERM=truecolor, shell /bin/fish
    • No plugins
    • Model: opencode/deepseek-v4.1-flash-free — note the provider is opencode, not opencode-go, and the model is the -free variant, no #variant

    What triggered it

    Not read, and not a user attachment. An MCP tool returned an image:

    1. MCP server ai-game-developer (Unity) exposes screenshot-game-view, which returns a PNG.
    2. Agent called it during a render-verification loop.
    3. Result: 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 image content — 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-execute calls 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 files part or a read result. 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 image parts 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 provider invalid_request_error for 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.

  4. aitools1 commented on Nov 4, 2026

    @aitools1

    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 -f in a fresh session, no prior images, no MCP tool result:

    opencode run -m opencode/deepseek-v4.1-flash-free -f imgtest.png "What shapes and colors are in this image?"
    -> Upstream request failed: [invalid_request_error] image input is not available on this engine (request_id: gw-ae0e2e66bcf8-192db7)
    
    opencode run -m "opencode/deepseek-v4.1-flash-free#max" -f imgtest.png "..."
    -> ... (request_id: gw-add10c6ab910-192efe)
    

    So an inline files part from a plain attachment is enough; no clipboard paste and no history re-send needed.

    More affected engine prefixes, none matching the gw-adac8a2c2d3d node above: gw-ae0e2e66bcf8, gw-add10c6ab910, plus gw-addc59e92621d, gw-addc3cc2c204, gw-adba25bd59c1 from six interactive attempts between 23:25 and 23:30 UTC on 2026-11-04.

    Regression window. Same model, same account, images worked on:

    • 2026-10-29 12:08–16:08 UTC — image/png attachments, assistant replies describe screenshot content.
    • 2026-10-31 12:36–16:48 UTC — image/png and image/jpeg attachments, 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; paid deepseek-v4.1-flash → Insufficient account funds.

  5. DaTurtleGuy commented on Nov 5, 2026

    @DaTurtleGuy

    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, -f attach 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 -free route 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 engine hit 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions