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
[V2 Desktop] Pasted images show no thumbnail when the active model is text-only #54991
On OpenCode Desktop 2.0.27 (Windows 11), when I paste an image into the prompt:
With a multimodal model (e.g. deepseek-v4.1-flash with modalities.input: ["text", "image"]), the image shows a thumbnail preview. Good.
With a text-only model (e.g. glm-5.2 with modalities.input: ["text"]), the image shows no thumbnail at all — it is silently stored as a file-path attachment (metadata.attachments: [{name, mime, path}]) with zero visual feedback.
The user has no way to tell whether the image was actually attached.
Why this matters
Text-only models are common in custom OpenAI-compatible providers. The attachment exists in the
message data but the chat UI renders nothing, so the paste looks like it did nothing.
A plugin can still process the file in the background, but the UI gives no indication of that.
What I would like
Show at least a thumbnail/file placeholder for image attachments even when the active model
does not declare image input support, or
Show a small warning that the image will not be sent to the model natively.
Related
Related to #47480 (images silently replaced by text placeholder).
Similar area as #21227 (tool-result image attachments not rendered).
Thanks for the clear write-up! You're asking for a visible preview, and ideally a short warning, when you paste an image while the active model is text-only (modalities.input: ["text"]), so it's obvious the image was attached and how the model will get it.
Some background: since #49467, when the selected model doesn't accept image input, Desktop attaches the image as a file path that the model can open with its tools, not as inline image data. In 2.0.27 these path attachments should still show up as a generic file card (filename plus a "PNG"/"JPG" label) in the composer and on the sent message. They just don't get an image thumbnail, and nothing explains that the model won't see the image itself. If you see no card at all, please reply and say so (a screenshot helps), because that would be a bug rather than a missing feature.
Maintainers will consider showing thumbnails for image path attachments and/or a hint about the model's image support. Related issues:
Yes — I do see the generic file card (image.png + PNG label) in both the composer and the sent message. So per your classification this is the missing-feature case, not the no-card bug.
Three specific pain points:
Multiple images are indistinguishable. Pasting several images shows identical cards (clipboard pastes are often all named image.png). No way to tell which is which.
No click-to-preview. The card can't be clicked to view the image, unlike thumbnails on vision-capable models. After sending, I can't verify what was actually attached.
Regression from V1. V1 desktop showed thumbnails regardless of the active model. V2 only shows them when the model declares image input, which makes text-only models (common with custom OpenAI-compatible providers, e.g. glm-5.2) feel broken.
Env: Windows 11, Desktop 2.0.27, glm-5.2 (modalities.input: [text]) via custom OpenAI-compatible provider.
A thumbnail for image path attachments (the file is local, so even a small preview would work) plus a one-line hint that the model receives it as a file path rather than inline image data would fully resolve this. Thanks for considering it.
One more thing worth mentioning: on my setup, pasted images do NOT break text-only sessions. I run a local plugin (vision-paste) that detects image attachments when the active model is text-only, transcribes them via a vision-capable model, and injects the description as text before the request is sent. So the image content still reaches the model — the only thing missing is UI feedback.
This confirms the gap is purely in the UI layer (thumbnail/preview + hint), not a capability problem. The data path works; only the visual confirmation is absent. If thumbnails were shown for path attachments, the whole flow would feel complete with no backend changes needed.
Update: still not fixed on Desktop 2.0.32 (Windows 11, installed 2026-10-17).
Retested in a fresh session with a text-only model (glm-5.2, modalities.input: ["text"]):
Pasted a screenshot → both the composer and the sent message show only the generic file card (image.png + PNG label). No thumbnail.
The 2.0.29 changelog item "render inline attachments before their server echo arrives" (#55251, #54650) does not cover this path — that one appears to apply only to models that accept image input. Re-verified as still broken on 2.0.32, so the regression window is now 2.0.27 → 2.0.28 → 2.0.29 → 2.0.32.
Concrete asks, in the order that would help most:
Thumbnail preview for path attachments — same rendering as the multimodal case. Cheapest possible fix since the image renderer already exists.
Distinguish multiple pasted images — clipboard pastes are all named image.png, so N attachments render as N identical cards with no way to tell them apart.
Click-to-preview — the card is not clickable, while thumbnails on vision-capable models are.
A one-line hint that the image was attached as a file path rather than silently dropped.
Worth repeating from my earlier comment, because it narrows the scope: the image content does reach the model on this setup. A local plugin transcribes image attachments for text-only models and injects the description as text before the request is sent. So the missing piece is purely UI feedback, not transport or capability.
I dug through the current dev tree to see how much work a thumbnail would actually be, because I'd rather hand you something actionable than another "please fix".
The two rendering paths are different
In packages/session-ui/src/message/message-content.tsx:
Lines 349-363 — inline attachments (message.files): mime.startsWith("image/") renders <img src="data:<mime>;base64,...">. Thumbnails work here. This is the multimodal path.
Lines 333-338 — path attachments (references, shape { name, mime, path } from SessionUserAttachmentReference): always<AttachmentCard> (title + typeLabel subtitle), with no image branch at all. This is the text-only path, and it's exactly what I see.
Why I don't think it's a small fix
For the path case the renderer only has a path, not bytes. The desktop protocol handler (packages/desktop/src/main/windows/protocol.ts) deliberately serves only the app bundle — it rejects any host other than rendererHost and resolves paths inside rendererRoot (lines 82-92). Attachments can only be handed to the OS via openAttachment. So a thumbnail needs a new controlled read channel (a dedicated protocol handler, or an IPC returning a data URL), which touches the renderer's file-access boundary. That's presumably why this has stayed in the backlog, and it's a reasonable call — no complaints from me.
What could ship without touching that boundary
All of these are pure UI, confined to attachment-card.tsx plus its one call site, so they carry no security-review burden:
A one-line hint on the card — e.g. Attached · the model reads this as a file path. This is the actual pain: after pasting, nothing confirms the image was attached at all.
Distinguish multiple pastes — clipboard pastes are all image.png, so N attachments render as N identical cards. An index, dimensions, or file size would make them tellable apart.
Show the size — image.png · 2.4 MB fits the existing subtitle slot, which already renders typeLabel.
If a thumbnail is out of scope for now, (1) alone would close the "did my paste actually work?" ambiguity that made me open this in the first place.
FWIW the data path is fine on my side: a local plugin transcribes path attachments for text-only models and injects the description as text before the request is sent, so the model does receive the image. Only the confirmation is missing.
Version: 2.2.1 (installed 2026-10-29, update from 2.2.0)
Model: glm-5.2 with modalities.input: ["text"] — a text-only model, i.e. exactly the case in the original report
Action: pasted a screenshot into the composer, then sent it
Result: the thumbnail now renders both in the composer and in the sent message. Previously both places showed only the generic file card (image.png + PNG label).
From the 2.2.1 bundle, AttachmentCard now carries readMedia / resolvedUrl / ImagePreview plus a placeholder style, so the path-attachment case gets real preview bytes instead of a static card. Combined with #59947 (request inline image bytes by default) this looks like the media-uri work (#59104, #59947) covered this scenario.
Feel free to close this if you consider it resolved — thanks for shipping it.
Activity
opencode-agent commentedon Oct 13, 2026
Thanks for the clear write-up! You're asking for a visible preview, and ideally a short warning, when you paste an image while the active model is text-only (
modalities.input: ["text"]), so it's obvious the image was attached and how the model will get it.Some background: since #49467, when the selected model doesn't accept image input, Desktop attaches the image as a file path that the model can open with its tools, not as inline image data. In 2.0.27 these path attachments should still show up as a generic file card (filename plus a "PNG"/"JPG" label) in the composer and on the sent message. They just don't get an image thumbnail, and nothing explains that the model won't see the image itself. If you see no card at all, please reply and say so (a screenshot helps), because that would be a bug rather than a missing feature.
Maintainers will consider showing thumbnails for image path attachments and/or a hint about the model's image support. Related issues:
wc4440222 commentedon Oct 13, 2026
Yes — I do see the generic file card (
image.png+PNGlabel) in both the composer and the sent message. So per your classification this is the missing-feature case, not the no-card bug.Three specific pain points:
image.png). No way to tell which is which.glm-5.2) feel broken.Env: Windows 11, Desktop 2.0.27,
glm-5.2(modalities.input: [text]) via custom OpenAI-compatible provider.A thumbnail for image path attachments (the file is local, so even a small preview would work) plus a one-line hint that the model receives it as a file path rather than inline image data would fully resolve this. Thanks for considering it.
wc4440222 commentedon Oct 13, 2026
One more thing worth mentioning: on my setup, pasted images do NOT break text-only sessions. I run a local plugin (
vision-paste) that detects image attachments when the active model is text-only, transcribes them via a vision-capable model, and injects the description as text before the request is sent. So the image content still reaches the model — the only thing missing is UI feedback.This confirms the gap is purely in the UI layer (thumbnail/preview + hint), not a capability problem. The data path works; only the visual confirmation is absent. If thumbnails were shown for path attachments, the whole flow would feel complete with no backend changes needed.
wc4440222 commentedon Oct 13, 2026
Update: tested on Desktop 2.0.28 — the issue persists. Text-only models still show only the generic file card with no thumbnail.
Note: changelog for 2.0.28 mentions Loaded
wc4440222 commentedon Oct 17, 2026
Update: still not fixed on Desktop 2.0.32 (Windows 11, installed 2026-10-17).
Retested in a fresh session with a text-only model (
glm-5.2,modalities.input: ["text"]):image.png+PNGlabel). No thumbnail.The 2.0.29 changelog item "render inline attachments before their server echo arrives" (#55251, #54650) does not cover this path — that one appears to apply only to models that accept image input. Re-verified as still broken on 2.0.32, so the regression window is now 2.0.27 → 2.0.28 → 2.0.29 → 2.0.32.
Concrete asks, in the order that would help most:
image.png, so N attachments render as N identical cards with no way to tell them apart.Worth repeating from my earlier comment, because it narrows the scope: the image content does reach the model on this setup. A local plugin transcribes image attachments for text-only models and injects the description as text before the request is sent. So the missing piece is purely UI feedback, not transport or capability.
wc4440222 commentedon Oct 22, 2026
I dug through the current
devtree to see how much work a thumbnail would actually be, because I'd rather hand you something actionable than another "please fix".The two rendering paths are different
In
packages/session-ui/src/message/message-content.tsx:message.files):mime.startsWith("image/")renders<img src="data:<mime>;base64,...">. Thumbnails work here. This is the multimodal path.references, shape{ name, mime, path }fromSessionUserAttachmentReference): always<AttachmentCard>(title +typeLabelsubtitle), with no image branch at all. This is the text-only path, and it's exactly what I see.Why I don't think it's a small fix
For the path case the renderer only has a path, not bytes. The desktop protocol handler (
packages/desktop/src/main/windows/protocol.ts) deliberately serves only the app bundle — it rejects any host other thanrendererHostand resolves paths insiderendererRoot(lines 82-92). Attachments can only be handed to the OS viaopenAttachment. So a thumbnail needs a new controlled read channel (a dedicated protocol handler, or an IPC returning a data URL), which touches the renderer's file-access boundary. That's presumably why this has stayed in the backlog, and it's a reasonable call — no complaints from me.What could ship without touching that boundary
All of these are pure UI, confined to
attachment-card.tsxplus its one call site, so they carry no security-review burden:Attached · the model reads this as a file path. This is the actual pain: after pasting, nothing confirms the image was attached at all.image.png, so N attachments render as N identical cards. An index, dimensions, or file size would make them tellable apart.image.png · 2.4 MBfits the existing subtitle slot, which already renderstypeLabel.If a thumbnail is out of scope for now, (1) alone would close the "did my paste actually work?" ambiguity that made me open this in the first place.
FWIW the data path is fine on my side: a local plugin transcribes path attachments for text-only models and injects the description as text before the request is sent, so the model does receive the image. Only the confirmation is missing.
wc4440222 commentedon Oct 29, 2026
Confirmed fixed on Desktop 2.2.1 (Windows 11).
glm-5.2withmodalities.input: ["text"]— a text-only model, i.e. exactly the case in the original reportimage.png+PNGlabel).From the 2.2.1 bundle,
AttachmentCardnow carriesreadMedia/resolvedUrl/ImagePreviewplus a placeholder style, so the path-attachment case gets real preview bytes instead of a static card. Combined with #59947 (request inline image bytes by default) this looks like the media-uri work (#59104, #59947) covered this scenario.Feel free to close this if you consider it resolved — thanks for shipping it.
Tarquinen commentedon Nov 2, 2026
Thanks for confirming it's fixed on 2.2.1! Closing this issue.
— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊