[Bug] Claude Code CLI exits with code 1 on Windows when processing image attachments

Status Open
Reported on v2.1.215
Maintainer reply None cached
Activity 0 comments · opened Jul 20, 2026

Bug Description
Attaching an image kills the Claude Code CLI backend on Windows (exit code 1, silent, 100% reproducible)

ENVIRONMENT

Windows 11 Home 10.0.22000
Claude Desktop 1.22209.3 (regression first seen on 1.22209.0)
Bundled Claude Code CLI 2.1.215, Electron 42.5.1
SYMPTOM Sending any message containing an image attachment causes the bundled backend claude.exe to exit immediately with code 1, printing nothing to stdout or stderr. The Electron app stays alive but the session dies, so it looks like a crash to the user. Text-only messages on the same path work fine. 100% reproducible. No Crashpad dump is produced, so this is not a native crash.

ISOLATED REPRO (without the app) Feed a stream-json user message containing a base64 image block directly to the CLI:

$b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes(".\test.png")) $obj = @{ type='user'; message=@{ role='user'; content=@( @{ type='image'; source=@{ type='base64'; media_type='image/png'; data=$b64 } }, @{ type='text'; text='what color is this' }) } } ($obj | ConvertTo-Json -Depth 10 -Compress) | Out-File .\msg.jsonl -Encoding utf8 -NoNewline Get-Content .\msg.jsonl | & "$env:APPDATA\Claude\claude-code\2.1.215\claude.exe" ` --input-format stream-json --output-format stream-json --verbose -p

Result: EXIT=1, stdout empty, stderr empty. --debug adds no output. Expected: the CLI processes the image and responds, as it did before the regression.

ISOLATION RESULTS

text-only content block -> exit 0 (works)
image block only / text+image / image+text / media_type image-jpeg -> exit 1
deliberately invalid block type (control) -> exit 1, i.e. the image block behaves exactly like an unknown block type. This plus the 0-second time-to-exit and total absence of output suggests the failure is in stream-json input validation/parsing, before any API request is made.
Not size-dependent: a 527-byte 64x64 PNG reproduces it.
Not config-dependent: still reproduces with --setting-sources= (no settings loaded); no hooks configured in settings.json.
REGRESSION TIMELINE (from %APPDATA%\Claude\logs\main.log, correlating imageCount=N sends)

CLI 2.1.209, Jul 15 07:08 - Jul 19 15:01: image sends SUCCEEDED (e.g. Jul 15 13:55, completed normally)
CLI 2.1.215, Jul 19 15:11 - present: image sends FAILED 4/4 (Jul 19 17:48; Jul 20 00:42, 00:50, 01:09)
Log excerpt: 01:09:15 [info] LocalSessions.sendMessage: ... imageCount=1, attachmentCount=0 01:09:15 [info] Using Claude Code binary at: ...\claude-code\2.1.215\claude.exe 01:09:19 [error] Session ... query error: Claude Code process exited with code 1 01:09:19 [info] [CCD CycleHealth] unhealthy cycle (4s, hadFirstResponse=false, reason=no_response)

WHAT IS NOT PROVEN

The desktop app (1.21459.x -> 1.22209.0 at Jul 19 15:04) and the CLI (2.1.209 -> 2.1.215 at Jul 19 15:10) were updated minutes apart, so the two are confounded; I cannot attribute the regression to the CLI bump alone from in-app evidence.
A separately installed CLI 2.1.210 also fails the isolated repro above. So either the defect predates 2.1.215 on that code path, or my isolated repro does not exactly match how the desktop app feeds images to the backend. Worth determining which, as it changes where to look.
SECONDARY ISSUE: session unrecoverable after the backend dies After the exit-1 crash the session can stay wedged as if work were still in flight, so re-sending is deferred and never drains; retry appears to do nothing and a new session is required. Log shows: [LocalSessionManager] isRunning held by unechoed input at result for local_... { hasPendingCycle: true, inputStreamHasPending: false } [CCD] Session ... torn down with 1 live background task(s) - settling as stopped (exited) Independent of the image bug, a backend process dying mid-cycle should not leave the session stuck.

WORKAROUND Save the image to disk and pass its path in a text-only message so the Read tool loads it; this avoids the failing path entirely.Attaching an image kills the Claude Code CLI backend on Windows (exit code 1, silent, 100% reproducible)

ENVIRONMENT

Windows 11 Home 10.0.22000
Claude Desktop 1.22209.3 (regression first seen on 1.22209.0)
Bundled Claude Code CLI 2.1.215, Electron 42.5.1
SYMPTOM Sending any message containing an image attachment causes the bundled backend claude.exe to exit immediately with code 1, printing nothing to stdout or stderr. The Electron app stays alive but the session dies, so it looks like a crash to the user. Text-only messages on the same path work fine. 100% reproducible. No Crashpad dump is produced, so this is not a native crash.

ISOLATED REPRO (without the app) Feed a stream-json user message containing a base64 image block directly to the CLI:

$b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes(".\test.png")) $obj = @{ type='user'; message=@{ role='user'; content=@( @{ type='image'; source=@{ type='base64'; media_type='image/png'; data=$b64 } }, @{ type='text'; text='what color is this' }) } } ($obj | Conver…
Note: Content was truncated.

View original on GitHub ↗