anomalyco / anomalyco/opencode
Images pasted with a custom-provider model are silently replaced by a "[Attached image/png: ...]" text placeholder — no warning, even when the upstream model has vision
@neriousy is already working on this.
Since Sep 5, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Description
When a model is defined under provider.<id>.models in opencode.json(c) (custom OpenAI-compatible provider), its attachment capability defaults to false unless explicitly set (the bundled model loader resolves attachment: cfg.attachment ?? false for custom models).
If the user pastes/attaches an image in such a session, OpenCode silently rewrites the media part into a plain text part:
[Attached image/png: screenshot.png]
No warning is shown in the TUI. The LLM only ever receives that placeholder — even when the model behind the endpoint fully supports vision. The model then typically hallucinates an explanation ("the current model does not support image input"), which actively misleads the user into concluding their vision model is broken.
Steps to Reproduce
- Define a custom provider with a vision-capable model, without
attachment:
{
"provider": {
"mygw": {
"options": { "baseURL": "http://localhost:PORT/v1", "apiKey": "{env:KEY}" },
"models": {
"my-vision-model": {
"name": "Vision model",
"limit": { "context": 1000000, "output": 65536 }
}
}
}
}
}
- Start a session on
mygw/my-vision-model. - Paste a screenshot containing visible error text and ask "what does this error say?".
- The model answers generically or claims it cannot see images. Inspecting the stored parts shows the image was replaced by the
[Attached image/png: ...]text part; the image itself never left OpenCode.
Expected Behavior
- A visible warning when media is attached to a model with
attachment: false(e.g. "model does not support attachments — the image will be sent as a text placeholder only"), or an explicit error instead of silent degradation. - The
attachment/modalitiesmodel keys documented on the custom providers page (I could not find them in the docs and only discovered them by inspecting the bundle).
Actual Behavior
Silent placeholder substitution; the conversation proceeds as if the image had been delivered, and the failure only surfaces as wrong/misleading model answers.
Workaround
Set the capability per model:
"my-vision-model": {
"attachment": true,
"modalities": { "input": ["text", "image"] }
}
After this, images are delivered natively — verified end-to-end on OpenCode 1.18.25 (CLI) and the desktop app bundling 1.18.29 against an OpenAI-compatible gateway with Gemini-class heads: the model transcribes pasted screenshots correctly.
Environment
- OpenCode 1.18.25 CLI + desktop app (bundled server 1.18.27–1.18.29), Windows 11
- Custom provider using the default
@ai-sdk/openai-compatibleroute
Notes
A related idea: when the active model lacks attachment capability but small_model (or any configured model) is vision-capable, OpenCode could optionally transcribe the image with that model and inject the description as a text part — a built-in fallback that would make images "just work" on text-only models. I currently run this as a chat.message plugin hook and it works well; happy to upstream the approach.
I'd genuinely like to collaborate with the team as a regular contributor — if you point me at where you'd want the warning (TUI vs server) or the fallback, I can prepare a PR.
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.