You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AI SDK route (aisdk:@ai-sdk/openai-compatible) sends tool-result images as null content parts #50960
With a provider on the AI SDK route aisdk:@ai-sdk/openai-compatible, an image returned by a tool (e.g. read on a PNG) is sent to the provider as a null content part instead of an image_url part.
opencode moves tool-result media into a follow-up user message (packages/core/src/aisdk.ts, "Attached media from tool result:"), but after the AI SDK conversion the image part is null:
{
"role": "user",
"content": [
{ "type": "text", "text": "Attached media from tool result:" },
null
]
}
Consequences:
the model never sees the image;
any server that iterates the content parts without a null check fails the request, and since the history is replayed on every turn, the session stays broken from then on (we hit this with a local OpenAI-compatible proxy: null is not an object (evaluating 'part.type')).
The native route does not have the problem: with package: "@opencode/ai/providers/openai-compatible" the same turn sends { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } }, and the model reads the image correctly.
Side difference, same capture: on the AI SDK route the preceding tool message content is the JSON-encoded array ('[{"type":"text","text":"Image read successfully"}]'), while the native route sends the plain text.
Steps to reproduce
Declare a provider with package: "aisdk:@ai-sdk/openai-compatible" and a model whose capabilities.input includes image, pointing baseURL at a server that logs request bodies.
Let the model call read on a PNG file.
Inspect the next /v1/chat/completions request: the last user message is ["text", null].
Switching only the provider package to @opencode/ai/providers/openai-compatible makes the same request carry the image_url part.
I was able to reproduce this on v2.0.15 (built from the tag), but the config in the issue as written doesn't trigger it on its own.
The literal config doesn't reach the AI SDK path.aisdk:@ai-sdk/openai-compatible matches the rewrite table in AISDKNative.rewrite() (packages/core/src/aisdk-native.ts), so it gets routed to @opencode/ai/providers/openai-compatible. The request comes out identical to the native route (correct image_url, no "Attached media from tool result:" text).
A version-pinned specifier does reproduce it. Both of these skip the rewrite, install @ai-sdk/openai-compatible@3.0.57 at runtime, and send the null part:
{"role":"tool","tool_call_id":"call_read_png","content":"[{\"type\":\"text\",\"text\":\"Image read successfully\"}]"}
{"role":"user","content":[{"type":"text","text":"Attached media from tool result:"},null]}
@krishna2206, did your config have a version suffix on the package, or something similar that avoided the rewrite?
Cause.@ai-sdk/openai-compatible 3.x implements specificationVersion: "v4", where a file part's data is a tagged object ({ type: "data" | "url" | ... }). fileData() in packages/core/src/aisdk.ts still returns the v3 shape (a raw base64 string / bytes / URL). The converter's switch (part.data.type) matches no case and returns undefined, which serializes to null. The same route with @ai-sdk/openai-compatible@2.0.41 (the version the monorepo pins) sends a correct image_url part.
The JSON-encoded tool message content from the original report happens on both 2.0.41 and 3.0.57, so that one looks like a separate issue.
@rekram1-node Thanks for clarifying the v2 direction. I'm contributing a fix for this report rather than relying on the AI SDK route for a separate use case.
PR #51482 targets the versioned specifiers described above (aisdk:@ai-sdk/openai-compatible@3 / @latest): they bypass the native rewrite and can silently serialize image parts as null because of the v3/v4 file-data contract mismatch. I agree that @opencode/ai/providers/openai-compatible is the preferred route here.
Given the plan to remove AI SDK support, would you prefer a clear error for unsupported AI SDK model versions, with guidance to use the native provider, instead of adding v4 compatibility? I'll hold off on further changes to #51482 until the intended scope is clear, and can revise or close it accordingly.
Activity
JosvanderWesthuizen commentedon Sep 26, 2026
I was able to reproduce this on
v2.0.15(built from the tag), but the config in the issue as written doesn't trigger it on its own.The literal config doesn't reach the AI SDK path.
aisdk:@ai-sdk/openai-compatiblematches the rewrite table inAISDKNative.rewrite()(packages/core/src/aisdk-native.ts), so it gets routed to@opencode/ai/providers/openai-compatible. The request comes out identical to the native route (correctimage_url, no"Attached media from tool result:"text).A version-pinned specifier does reproduce it. Both of these skip the rewrite, install
@ai-sdk/openai-compatible@3.0.57at runtime, and send thenullpart:{"role":"tool","tool_call_id":"call_read_png","content":"[{\"type\":\"text\",\"text\":\"Image read successfully\"}]"} {"role":"user","content":[{"type":"text","text":"Attached media from tool result:"},null]}@krishna2206, did your config have a version suffix on the package, or something similar that avoided the rewrite?
Cause.
@ai-sdk/openai-compatible3.x implementsspecificationVersion: "v4", where a file part'sdatais a tagged object ({ type: "data" | "url" | ... }).fileData()inpackages/core/src/aisdk.tsstill returns the v3 shape (a raw base64 string / bytes /URL). The converter'sswitch (part.data.type)matches no case and returnsundefined, which serializes tonull. The same route with@ai-sdk/openai-compatible@2.0.41(the version the monorepo pins) sends a correctimage_urlpart.The JSON-encoded
toolmessage content from the original report happens on both 2.0.41 and 3.0.57, so that one looks like a separate issue.aisdk:@ai-sdk/openai-compatibleimage_url✅aisdk:@ai-sdk/openai-compatible@3/@latest(3.0.57)null❌image_url✅@opencode/ai/providers/openai-compatibleimage_url✅Suggested fixes:
specificationVersionon AI SDK models and emit the v4 part shape (or reject v4 models with a clear error instead of silently sendingnull).aisdk:packages to a compatible major when no version is given.Repro (mock OpenAI-compatible server that logs request bodies and scripts a
readcall on a PNG, all six provider variants above): https://gist.github.com/JosvanderWesthuizen/b300022e40b6da969889ea579a2a03cdEthereal49 commentedon Sep 26, 2026
I’m working on a v2 fix for versioned AI SDK providers using the v4 file-data contract, with regression coverage for v3 and v4 media serialization.
rekram1-node commentedon Sep 26, 2026
On v2 you shouldn't be using the aisdk. We will eventually drop support for it altogether, why are u using the aisdk instead of the native route?
@opencode/ai/providers/openai-compatible
Ethereal49 commentedon Sep 27, 2026
@rekram1-node Thanks for clarifying the v2 direction. I'm contributing a fix for this report rather than relying on the AI SDK route for a separate use case.
PR #51482 targets the versioned specifiers described above (
aisdk:@ai-sdk/openai-compatible@3/@latest): they bypass the native rewrite and can silently serialize image parts asnullbecause of the v3/v4 file-data contract mismatch. I agree that@opencode/ai/providers/openai-compatibleis the preferred route here.Given the plan to remove AI SDK support, would you prefer a clear error for unsupported AI SDK model versions, with guidance to use the native provider, instead of adding v4 compatibility? I'll hold off on further changes to #51482 until the intended scope is clear, and can revise or close it accordingly.
fix(provider): use opencode's native providers so image input works
rekram1-node commentedon Oct 5, 2026
btw we aren't going to support ai sdk v7, so if u rlly need to use aisdk I recommend you pin ur versions. We will try to only install v6 by default.
I'm going to close this issue since v7 support definitely isnt in scope but I have some related prs ill merge