Repository navigation
Description
Description
Version: OpenCode v2.0.24 (checked against the sources at tag v2.0.24, commit e7a34f09bf)
Summary
If a tool result contains a file whose media type is not an image, a PDF, or (on the Anthropic route only) text/plain, the request builder of the active provider route rejects the whole request. The result stays in the session history, so every following prompt rebuilds the same request and fails with the same error. The session cannot continue unless the user reverts past that tool call.
Observed error (Anthropic Messages route):
provider.invalid-request: Anthropic Messages does not support media type text/x-patch
The same check exists in the OpenAI Chat builder (OpenAI Chat does not support media type …), so this is not specific to one provider.
Reproduction (from a real session)
- Use any model on the Anthropic Messages route.
- Call an MCP tool that returns attachments. In my case the tool downloaded the attachments of an issue and returned three parts: a text part, a
text/x-patchfile and animage/pngfile. - The step that produced the tool result succeeds. The next model call, which sends the tool result back, fails with the error above.
- Every later prompt in the same session fails with the same error, because the history still contains the tool result.
The file part reaches the history as data:text/x-patch;base64,… with mime: "text/x-patch" (MCP server declares the type; core/src/tool/mcp.ts copies it unchanged into a file content item).
Where it happens
packages/core/src/mcp/client.ts(toCallToolResult) turns MCPimage,audioand blobresourceparts intomediaparts with the server'smimeType.packages/core/src/tool/mcp.tsturns every non-text part into{ type: "file", uri: "data:<mime>;base64,…", mime }.packages/core/src/session/model-request.tsrunsunsupportedParts(...)before building the request. ItsunsupportedMediaonly replaces media with an explanatory text whenmimeToModality(mime)returns a modality (image/*,audio/*,video/*,application/pdf) that the model does not list incapabilities.input. For any other media type,mimeToModalityreturnsundefined, so the part passes through unchanged.packages/ai/src/protocols/anthropic-messages.ts,lowerMedia: accepts images,application/pdfandtext/plain; every other type ends ininvalid("Anthropic Messages does not support media type …")(line ~768).lowerToolResultContentItemroutes tool-result files through this function.packages/ai/src/protocols/openai-chat.ts,lowerMedia: accepts PDFs and images, otherwiseinvalidRequest("OpenAI Chat does not support media type …").
packages/ai/src/media.ts kindOf classifies every text/* type as document, which makes the builders' behavior look broader than it is.
Why this is a bug and not only an unsupported feature
- A failing optional attachment aborts the whole request, including the user's own next prompt.
- The failure is permanent for the session, because the history is the source of every later request.
- Core already has a mechanism for this exact situation (
unsupportedMediareplaces media the model cannot read with anERROR: Cannot read …text), but it is keyed on modality and the model'scapabilities.input, so it does not cover types that have no modality, and it does not know what the selected route can actually encode. - The tool author and the model provider are not under the user's control. An MCP server may legitimately return any media type.
Expected behavior
One of the following, in order of preference:
- Media that the selected route cannot lower is replaced by a short text note (as
unsupportedMediaalready does for known modalities), so the request succeeds and the model can tell the user the file could not be read. - Textual types (
text/*,application/json, and similar) are sent as text. The Anthropic builder already does this fortext/plaindocuments. - At least, the error should not poison the session: a failed lowering of a tool-result part should not fail later requests.
Suggested fix
In unsupportedMedia (or a route-aware step next to it), treat any media type that is not image/*, audio/*, video/* or application/pdf as unsupported unless the route declares support. For text/*, re-type to text/plain or inline the decoded text. A test can follow the existing one in packages/ai/test/provider/anthropic-messages.test.ts ("rejects tool-result media that cannot be lowered"), which currently pins the rejecting behavior for audio/mpeg; a core-level test should show that text/x-patch in a tool result no longer fails the request.
Workaround
A plugin can edit event.messages in the context session hook (the built-in plugins plan and warming do this) and re-type or replace the unsupported parts in tool results. It must run before the request is built. The history is not changed, so a session that already failed starts working again.
Environment
- OpenCode v2.0.24, Linux
- Route:
@opencode/ai/providers/anthropic(Anthropic Messages) through a LiteLLM gateway - Tool: an MCP server tool that returns attachments (text,
text/x-patch,image/png)
Plugins
mcp-atlassian
OpenCode version
v2.0.24
Steps to reproduce
- You need
mcp-atlassian - A Jira ticket containing a
.patchpatch file - A prompt like: Read ticket ..., especially the attached patch file and summarize it.
Screenshot and/or share link
No response
Operating System
Linux Fedora
Terminal
kitty
Activity
opencode-agent commentedon Oct 12, 2026
Thanks for the detailed analysis! I think this is a duplicate of #52448. In that issue, an MCP tool result with a media type the route can't encode (
application/vnd.apache.parqueton OpenAI Chat) is saved in the history, and every later request in the session then fails. It's the same cause you traced:unsupportedMediaonly covers types that map to a modality, so other types reach the route'slowerMediaand get rejected.Possible duplicates and closely related issues, ordered from most to least likely:
text/x-patch) would still fail. Your notes on the Anthropic path and the core-level fix would be a useful addition there.The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
maggu2810 commentedon Oct 13, 2026
This is not about binary but a general mime type regression (I think so).
And easily to reproduce with the Atlassian MCP.
Reading attachements high potentially result into non working session that has to be reverted to the previous message.
Now I got:
Anthropic Messages does not support media type text/markdownbecause the Jira ticket has a .md file attached.
opencode-agent commentedon Oct 13, 2026
Thanks for the follow-up. You're right that this goes beyond the binary-file case in #52448, so I'm keeping this issue open.
I reproduced it on v2.0.24, and it still happens on the latest
dev(4ffede4):text/markdownresource blob and a PNG image.@opencode/ai/providers/anthropic), pointed at a local mock endpoint. The mock only makes the model call the tool through Code Mode.Anthropic Messages does not support media type text/markdownand never reaches the endpoint, because it fails while OpenCode builds the request.The script below reproduces it end to end, with no provider credentials needed.
The rejecting check in the Anthropic request builder hasn't changed since at least v2.0.17. So rather than a recent regression, it looks like no
text/*type other thantext/plainhas ever been handled on this route. Core only replaces unsupported media for image, audio, video and PDF types, sotext/markdownandtext/x-patchreach the builder unchanged. Related: #52448 (same problem on OpenAI Chat). Its open fix, #52517, only changes the OpenAI Chat adapter and does not cover the Anthropic route.Reproduction script (repro.sh)
Run it:
bash repro.sh