[BUG] Windows image paste (Alt+V) fails in Claude Code but works in Codex CLI on the same terminal/clipboard
Image paste via Alt+V fails on Windows, and I can rule out the terminal, the clipboard format, and keystroke interception via a same-environment cross-tool control.
Environment
- Windows 10 Home (19045)
- Windows Terminal (native Win32 console host — not VS Code/Electron)
- Claude Code v2.1.201 (well past the v2.1.157 WSL/BMP fix, so this is not that already-"fixed" case)
Steps to reproduce
- Take a screenshot with
Win+Shift+S(a standard bitmap is placed on the clipboard). - Confirm the clipboard really holds the image by pasting into Paint/Word — it works.
- In Claude Code (Windows Terminal), press
Alt+V.
Result: Claude Code reports "no image in clipboard", although the image is verifiably present.
Key data point — same clipboard, same terminal, different tool:
In the same Windows Terminal, with the same clipboard contents, Codex CLI pastes the image with no problem. This isolates the failure to Claude Code's own Windows clipboard-image read path.
Related, already-closed issues that were never actually fixed: #57316 (closed as duplicate of #4272, which was bot-closed & locked) and #61883 (a failed paste also wipes the clipboard, closed as not planned).
Working workarounds: drag-and-drop, and typing a file path.
4 Comments
Additional, stronger isolation — same Claude Code binary, different terminal host, different behavior:
On the exact same machine with Claude Code v2.1.201:
Alt+Vpastes the clipboard image successfully.Alt+Vwith the same clipboard contents reports "no image in clipboard" and fails.Nothing changes except the terminal host — no different tool, no different clipboard, no different image. This points the problem specifically at how Claude Code reads keyboard/clipboard input under the Windows Terminal host (ConPTY) versus the classic conhost, rather than at the clipboard format or the image itself.
So on Windows there are now two independent controls isolating the bug to Claude Code's Windows input/clipboard path:
Root cause found. The terminal host (Windows Terminal vs conhost) was never the real variable — the working directory Claude Code is launched from is. I've confirmed this by reverse-engineering the v2.1.201 binary and with live counter-tests.
TL;DR
When
claudeis launched with its cwd set toC:\Windows\System32(orC:\Windows, or evenC:\), every internal spawn ofpowershellis silently blocked by Claude Code's own "unsafe location" guard, and the failure is misreported as "No image found in clipboard". Launch the same binary from any normal directory (e.g.%USERPROFILE%) in the same Windows Terminal, andAlt+Vpastes images fine.The defect
Internal spawns go through a safe-spawn wrapper (minified
Gv) that resolves bare command names viawhere.exeand then rejects any candidate that is "in an unsafe location (current directory)". The check (minifiedHdn) is:The second clause is a whole-subtree prefix match, not a "same directory" check. So with cwd =
C:\Windows\System32, the onlywhere.execandidate —— starts with
c:\windows\system32\and is rejected as "unsafe".GvthrowsCommand 'powershell' not found or is in an unsafe location (current directory), the clipboard-read function (minifiedbPe) swallows the exception in itscatchand returnsnull, and the UI reports "No image found in clipboard" — masking a spawn-policy failure as an empty clipboard.Evidence
WT_SESSIONset), I manually ran the verbatim commands Claude Code uses:checkImage:powershell -NoProfile -NonInteractive -Sta -Command "Add-Type -AssemblyName System.Windows.Forms; if (-not [System.Windows.Forms.Clipboard]::ContainsImage()) { exit 1 }"→ exit 0 (~200 ms)saveImage(GetImage + Save PNG to%TEMP%\claude_cli_latest_screenshot.png) → exit 0, PNG written.where.exe powershell, apply theHdnchecks):C:\Windows\System32→ the single candidate is rejected → resolution returnsnull.C:\Users\<user>→ same candidate accepted.claudefromC:\Users\<user>makesAlt+Vimage paste work; starting it fromSystem32reproduces the failure.Why the original WT-vs-conhost differential was misleading
My Windows Terminal had
"startingDirectory": nullinprofiles.defaults, and elevated launches then land inC:\Windows\System32— so claude inherited cwd = System32 there. The cmd/conhost control test happened to start in%USERPROFILE%. Same binary, same clipboard; the hidden variable was the cwd all along. (Codex CLI worked in the same WT simply because it has no such cwd guard.)Impact & suggested fix
C:\/C:\Windows/C:\Windows\System32, any internal direct spawn of a System32 binary is blocked by the same guard.dirname(candidate) === cwd(the actual CWD-hijack threat model), or exempt trusted system directories (%SystemRoot%subtree resolved viawhere.exeis not attacker-controlled).not_found/clipboard_read_failedinternally; the user-facing message should distinguish them too).Workaround for anyone hitting this: don't launch
claudefromC:\Windows\System32(e.g. an elevated shell's default directory) —cdto your project or home directory first, and/or set Windows Terminal'sstartingDirectory.Confirming the same issue on my setup:
Environment:
Symptoms:
Same clipboard contents work fine in other apps (Paint/Word), so it does look like it's isolated to Claude Code's Windows clipboard/drag-drop handling, consistent with what's reported here and in #26679 / #32791.
Can confirm Alt+V works for me — successfully pasted a Win+Shift+S screenshot into Claude Code CLI.
Environment:
This is a newer Claude Code version than the one reported here (v2.1.201), so this may have been fixed in between. Might be worth checking if this is still reproducible on the latest version.