Skip to content

sessions with image parts in history wedge forever in an endless 'model does not support images' loop #55309

Closed as duplicate

Description

@FahadBinHussain

what happens

a session becomes permanently wedged when its message history contains image parts and the selected model has no vision support. every continuation re-sends the full history, the provider rejects it with a non-retryable capability error, and the same error renders endlessly in the tui ("This model does not support images." hundreds of times). nothing new gets persisted and the storm of retry renders garbles the transcript view into unreadable glyphs.

how image parts get there

ordinary use. most commonly tool results that embed screenshots — parts of shape {"type":"file","uri":"data:image/..."} inside content[].state.content[] of assistant messages. once one exists in history, every future send includes it.

why it never recovers

the rejection is deterministic, not transient — no retry can ever succeed — but the error path behaves like a retryable failure: the same message keeps being produced and rendered. on top of that, the repeated sends showed up in logs as Failed to drain Session: ... Rate limit exceeded spam (the same wedge family as #54538).

expected behavior, either one:

  • strip or degrade image parts to text placeholders before sending when the active model declares no image support, with a one-time visible notice, or
  • fail once with a clear actionable error ("this session contains N image parts, model X cannot accept images") and stop looping

repair path that worked (2.0.23)

  1. opencode session export <id> — works, includes full content states
  2. replace the data:image file parts wholesale with text placeholders (blanking only the uri just turns into a "file not found" failure)
  3. regenerate all message ids — see next defect
  4. opencode session import — verified: same title, all messages, zero image uris

secondary defect: session import 500s on reused message ids with no useful error

importing an exported session fails with Failed to import session: Internal Server Error. the server logs an EffectDrizzleQueryError with the query and params but never surfaces the driver error to the client. cause: the export's message ids already exist in session_message (the original session still exists), so the insert hits a unique constraint. a fully synthetic session imports fine; any clone with reused message ids fails.

expected: re-key ids on import automatically, or at least report "message id already exists" instead of a bare 500.

secondary defect: unique (session_id, seq) 500s on the model endpoint

in the same window, unrelated live sessions on the same instance produced:

SQLiteError: UNIQUE constraint failed: session_message.session_id, session_message.seq

on POST /api/session/<id>/model (http 500). possibly the same write path — seq assignment may not be monotonic under concurrent writes. including it because it appeared alongside the above and looks related.

environment

Activity

  1. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed write-up and the repair steps! I think this is a duplicate of #52042.

    In v2, image parts already in the session history are checked before every request (unsupportedParts in packages/core/src/session/model-request.ts). That check replaces each image the model can't accept with a short ERROR: Cannot read … text note. It only does this when the model's capabilities.input leaves out image. A custom-provider model with no declared capabilities defaults to input: ["text", "image"]. So the stored screenshots are sent anyway, and the provider rejects every turn. The "This model does not support images." text comes from your provider.

    Workaround: declare the capabilities on your custom model, for example:

    "capabilities": { "tools": true, "input": ["text"], "output": ["text"] }

    The check runs over the whole stored history on every request, so this should also fix sessions that are already stuck. You shouldn't need the export/edit/import repair. Switching the session to a model that accepts images also gets it working again.

    Possible duplicates and related issues, ordered by likelihood:

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. FahadBinHussain commented on Oct 14, 2026

    @FahadBinHussain
    Author

    thanks for the triage, this matches what we found. Closing as duplicate.

    one addition worth checking: it's not only custom-provider models. the built-in opencode/mimo-v2.6-flash-free on the zen free tier also declares no capabilities, so it falls into the same input: ["text","image"] default and wedges identically when screenshots end up in tool results. we applied the capabilities override locally (provider.opencode.models."mimo-v2.6-flash-free" with input: ["text"]) — if that override can't extend built-in providers, the built-in model definitions probably need the declaration upstream as part of the #52042 fix.

    also +1 on the import 500 (#54336): our workaround was regenerating every message id before import, which then succeeds. an explicit conflict error or auto re-key would have saved a lot of digging.

  3. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for confirming, and for the extra details!

    MiMo on Zen: the local override is the right fix, and it does work for built-in providers. Entries under provider.opencode.models.<id> in config have their capabilities applied on top of the built-in model (the merge in packages/core/src/plugin/provider/opencode.ts, also in 2.0.23). With input: ["text"], image parts in the history, including tool-result screenshots, are swapped for a short text note before each request.

    One correction, though: mimo-v2.6-flash-free doesn't fall back to the default. The models.dev catalog that OpenCode uses declares its input as ["text", "image", "audio", "video"], so OpenCode sends images on purpose. In #54538 you also found that a fresh session with this model and a pasted PNG worked. If the Zen free tier really does reject images for this model, the catalog entry is what needs fixing, and that's tracked on models.dev. Adding that case to #52042 would help too.

    Import 500: please add your +1 and the workaround (regenerating every message ID before import) on #54336, so they're tracked with that issue.

    As said earlier, the bot will close this one as a duplicate of #52042.

  4. opencode-agent commented on Oct 15, 2026

    @opencode-agent
    Contributor

    Closing this as a duplicate of #52042, as discussed. Thanks again for the detailed report and the repair steps!

    Where to follow each part:

    If Zen keeps rejecting images for mimo-v2.6-flash-free even though the catalog says it accepts them, please add that case to #52042 or report it on models.dev.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions