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
Images read via the read tool bypass the model capabilities gate — persistent 400 errors and unusable sessions (also triggered by switching models) #51873
In OpenCode v2, the capability gate that strips unsupported media from user attachments does not apply to images returned by the read tool. The image is stored as a base64 data URI inside the session history (tool part state.content) and is sent to models whose input capability is text-only (e.g. glm-5.3 with input: ["text"]).
The provider then rejects every request:
Error: messages.content.type is invalid, allowed values: ['text']
The failed assistant message persists in history, so all subsequent requests in that session fail with the same 400 — the session becomes permanently unusable. There is no in-app way to remove the media from history.
There is also a second path that involves no tool call at all: a session where a vision-capable model previously read images gets killed by simply switching the session's model to a text-only one, because the stored images are now sent to a model that cannot accept them.
Reproduction — Path A (read tool)
Use a text-only model (e.g. glm-5.3, capabilities input: ["text"])
Ask the agent to read a local image file (the read tool returns it as a base64 data URI)
The image bypasses the capabilities gate and is included in the LLM request
GLM API returns 400; the failed message stays in history; every follow-up turn fails with the same 400 (session dead)
Observed live (2026-09-28): a session accumulated 4 image file parts (~8.5 MB base64) in history; every subsequent request failed with 400 in ~300 ms until the history was manually repaired.
Reproduction — Path B (model switch)
With a vision-capable model (e.g. glm-5.3-flash, input: ["text","image",...]), read an image — this passes, as it should
Switch the session's model to a text-only one (e.g. glm-5.3)
The next request includes the stored image → 400 → session dead
Expected
The request composer should apply the same capability gate to image outputs of the read tool (file parts in tool state.content) as it does to user attachments — replace with a short text notice (or exclude) when the model's input capabilities do not include "image". Because filtering happens at request-composition time, this would also fix Path B (model switching).
Actual
400 messages.content.type is invalid, allowed values: ['text'] on every request; session marked failed. Recovery required directly editing the session DB (replacing base64 blobs in session_message.data with a text notice) — no in-app recovery path exists.
Notes
Videos appear to take a different path (excluded from the LLM message), so images and videos are treated asymmetrically.
Local workaround in use: a plugin hooking execute.before on the read tool that blocks image reads for text-only models. Effective for Path A; cannot prevent Path B since model switching is not a tool call.
Three live occurrences in a single day of normal use, all on GLM.
Environment
opencode: v2.0.18 (Windows standalone binary)
OS: Windows 11 Pro (10.0.26200), x64
Terminal: Orca embedded terminal
Shell: cmd.exe
Install: release channel
Plugins: 15 local files auto-scanned from ~/.config/opencode/plugins (includes the custom read-blocking gate described above)
Activity
github-actions commentedon Sep 28, 2026
This issue might be a duplicate of existing issues. Please check: