Repository navigation
Custom OpenAI-compatible providers: image file attachments do not reach vision-capable models correctly #20802
Description
Summary
When using a custom OpenAI-compatible provider, image attachments sent through OpenCode sessions are not reaching the model as usable vision input.
In my case:
- provider:
longent - model:
gpt-5.4(xhigh) - transport: OpenCode desktop / session API
The exact same provider/model can successfully answer a vision request when called directly via the provider's OpenAI-compatible /chat/completions API using image_url.
But when I send an image through OpenCode as a file part (mime: image/png), the assistant responds with:
I can't read
remote-test.pnghere because this model doesn't support image input.
So this looks like an OpenCode adapter/translation issue in the custom provider + file attachment path, not a model capability issue.
Expected behavior
If a custom OpenAI-compatible provider/model supports image input, sending an image attachment through OpenCode should be translated into a valid multimodal request and the model should be able to read the image.
Actual behavior
OpenCode session messages with file image parts end up behaving as if the model does not support image input, even though the same model works with direct API vision calls.
Repro
1. Configure a custom OpenAI-compatible provider
Example config shape:
{
"provider": {
"longent": {
"name": "Longent",
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://longent.tech/v1",
"apiKey": "REDACTED"
},
"models": {
"gpt-5.4(xhigh)": {
"name": "GPT-5.4 XHigh",
"options": {
"reasoningEffort": "xhigh"
}
}
}
}
}
}2. Direct provider API works
A direct request to the same provider/model with image_url succeeds.
Example payload:
{
"model": "gpt-5.4(xhigh)",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What color is this image? Reply with one word."},
{"type": "image_url", "image_url": {"url": "https://dummyimage.com/10x10/ff0000/ffffff.png"}}
]
}
],
"max_tokens": 30
}Response is correct (red / Red).
3. OpenCode session API fails for image file attachment
Create a session, then send a message with parts:
{
"model": {"providerID": "longent", "modelID": "gpt-5.4(xhigh)"},
"agent": "build",
"parts": [
{"type": "text", "text": "What color is this image? Reply with one word."},
{
"type": "file",
"mime": "image/png",
"filename": "remote-test.png",
"url": "https://dummyimage.com/10x10/ff0000/ffffff.png"
}
]
}Returned assistant text:
I can't read `remote-test.png` here because this model doesn't support image input.
Additional observations
- I also reproduced the issue from the OpenCode desktop app by attaching a local PNG file.
- In the recorded session message, the user input is stored as a
filepart withmime: image/png. - The session itself is definitely using the custom provider/model (
providerID=longent,modelID=gpt-5.4(xhigh)). - This strongly suggests the problem is in how OpenCode maps
fileimage parts for custom OpenAI-compatible providers.
Environment
- OpenCode desktop
- OpenCode session version observed:
1.3.13 - macOS
Hypothesis
OpenCode may be handling image attachments correctly for some built-in providers, but for @ai-sdk/openai-compatible custom providers it looks like file image parts are not being converted into the multimodal format the upstream model expects.
Possibly the provider path needs to translate image file parts into something equivalent to image_url / image content parts for OpenAI-compatible chat requests.
Activity
github-actions commentedon Apr 3, 2026
This issue might be a duplicate of existing issues. Please check:
@ai-sdk/openai-compatiblehave image attachments silently stripped because vision capability (SupportsAttachments) is hardcoded for built-in providers only, not inherited by custom providersIf your issue is distinct (e.g. specifically about the
filepart →image_urltranslation path rather than capability gating), please clarify the difference.GravityPoet commentedon Apr 3, 2026
Thanks — I checked the suggested duplicates and added one more data point from my side.
What I verified locally:
longentgpt-5.4(xhigh)image_url.https://longent.tech/v1/chat/completionsfilepart in a session message.fileimage/pngSo from my testing, this is at least one of:
file(image/*)parts are not being translated correctly for OpenAI-compatible providersIf #8875 already covers the capability-gating root cause, then this issue may be the same bug manifesting through the session
fileattachment path.If helpful, I can also provide a minimal repro using:
image_urlparts: [text, file]XIYBHK commentedon Apr 21, 2026
Adding root-cause analysis and a workaround after digging through the opencode source.
Root cause: the
modalitiesfield is required but undocumentedCapability detection for image input lives in
packages/opencode/src/provider/provider.ts, roughly:If
modalitiesis not defined on a custom model entry inopencode.json,capabilities.input.imagedefaults tofalse, and image parts are stripped client-side before the request is built. The model then receives text only and often replies literally "I don't support image input", which looks like a backend capability issue but is actually opencode's own gating check.This explains why the same backend works with a direct
image_urlcurl but fails through opencode — thefile→image_urlmapping logic is never reached, because the attachment is already gone by then.Minimal repro
{ "$schema": "https://opencode.ai/config.json", "provider": { "my-kimi": { "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "https://your-openai-compatible-gateway/v1", "apiKey": "sk-..." }, "models": { "kimi-k2.5": { "name": "Kimi K2.5" // no `modalities` → image gets stripped client-side } } } } }Attach an image, send → assistant responds "I don't support image input."
Workaround: declare
modalitiesexplicitlyRestart opencode (the capability cache is built at startup, not hot-reloaded). Images now flow through correctly, verified end-to-end with Kimi K2.5 and K2.6 multimodal responses.
Suggestions
modalitiesunder the "Custom provider" section atopencode.ai/docs/providers. It's currently referenced nowhere in user-facing docs, even though it's the only switch that enables vision for custom providers.opencode.jsonJSON schema soprovider.*.models.*describesmodalities,reasoning,toolCall,temperature, etc. explicitly. Right now the inner model-entry shape is unconstrained, so IDE completion and schema validation give users zero hint thatmodalitiesexists.modalities.input.image, surface a warning. That would turn a confusing symptom ("model says it doesn't support images") into an actionable one ("opencode stripped your image becausemodalities.inputdoesn't include 'image'").Happy to open a docs PR for the first suggestion above.
f-trycua commentedon May 1, 2026
Ran into the same root cause with
gemma4:26bvia Ollama (@ai-sdk/openai-compatible). The fix is to explicitly declaremodalitiesinconfig.jsonfor the model — this field exists inprovider.tsbut is completely undocumented:{ "provider": { "ollama": { "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "http://localhost:11434/v1" }, "models": { "gemma4:26b": { "modalities": { "input": ["text", "image"], "output": ["text"] } } } } } }Without this,
capabilities.input.imagedefaults tofalsefor all custom provider models and images are replaced with"ERROR: Cannot read image (this model does not support image input). Inform the user."before they ever reach the model.Allowed values for
modalities.input/modalities.output:"text","audio","image","video","pdf".Also worth noting: even with this fixed, MCP tool results containing images still go through the synthetic-user-message detour (not the native tool-result path) because
@ai-sdk/openai-compatibleis not in thesupportsMediaInToolResultsallowlist inmessage-v2.ts. Images arrive at the model but as a separate user turn rather than inline in the tool result.rekram1-node commentedon May 1, 2026
That's because the completions api doesnt support tools returning images
12 remaining items
ngutech21 commentedon May 30, 2026
I can confirm the same behavior with LM Studio + Gemma 4 26B.
Setup:
@ai-sdk/openai-compatiblehttp://127.0.0.1:1234/v1gemma-4-26b-a4b-it-mlxtype: "vlm"Direct API calls to LM Studio worked correctly with an OpenAI-compatible
image_urlpayload, including streaming requests. The model could describe the image successfully.However, when attaching the same image through OpenCode, OpenCode stored the image as a
filepart, but the request sent to LM Studio did not include an image. Instead, LM Studio received text like:Adding
modalitiesto the custom model config fixed it:After this, image attachments work through OpenCode.
So this seems to be a documentation/discoverability issue for custom OpenAI-compatible vision models: without
modalities.inputincluding"image", OpenCode gates the image attachment before it reaches the provider.Looking forward to seeing the fix merged, since this small config detail makes local VLMs work nicely with OpenCode.
VL4DST3R commentedon May 30, 2026
I ended up patching the bundled app.asar myself using qwen 3.6 to implement the changes of this pr - and it seems to work just fine (tested with koboldcpp).
If anyone else is desperate to get it working like I was, consider doing the above. Note that you need to find the current chunk file name and exact byte strings to edit it for your version of opencode. Every update the chunk hash changes or minification tweaks the output, so you will need to find it again and repatch it.
Santelomar commentedon Jun 10, 2026
I'm experiencing the exact same issue while using LM Studio with Gemma-4 (Vision capable).
This is a critical blocker for my professional workflow. I am using the Godot MCP (GoPeak) which has the capability to capture screenshots for visual debugging, but because of this bug in OpenCode Desktop, the model remains "blind" to those captures and claims it doesn't support image input.
It's extremely frustrating because the model works perfectly in other environments, but the OpenAI-compatible adapter in OpenCode is failing to translate image attachments correctly. This makes UI/UX development and visual error tracking nearly impossible.
The solution here: #30071 👌 works fine but there are many things that should hopefully work within the Desktop version probably automatic as a default to recognize which model capabilities so we won't need to define it manually in the
opencode.jsoncfile.Please prioritize a fix for the OpenAI-compatible provider's image handling.
HUGE THANKS to anyone who help in the dev of the Desktop version, keep up the good work 🙏
fix(provider): enable image support for custom OpenAI-compatible prov…
github-actions commentedon Aug 9, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.
hadifarnoud commentedon Oct 16, 2026
I tried new
/connectto connect to digitalocean but still get thisError: 400: {"message":"unsupported multimodal content: image_url","type":"invalid_request_error"}error.it's frustrating to say the least
rekram1-node commentedon Oct 16, 2026
Hmm
rekram1-node commentedon Oct 16, 2026
Looks like bug on digitalocean side, contacting them
rekram1-node commentedon Oct 16, 2026
@hadifarnoud talked w/ digitalocean, I assume u tried
glm-5.3-flashsince that's the only model I could repro w/. Currently it doesn't support images but they are working on a fix, for now ill update our model catalog to say it doesnt support images to mitigate this issue for u.rekram1-node commentedon Oct 16, 2026
anomalyco/models.dev#10162
on opencode v2 models list refreshes every 10 min or so so itll automatically get picked up
hadifarnoud commentedon Oct 17, 2026
yes @rekram1-node that is exact model I have issue with.
rekram1-node commentedon Oct 17, 2026
Yeah, can't do anything on our end aside from marking it a non vision model so that if the model reads image files it wont brick the session. Waiting on them to fix it on their end so we can restore vision capabilities in OC.