DEV Community

Cover image for Claude Code on Windows breaks without errors: 15 traps I reproduced
上条碧人
上条碧人

Posted on Fully Autonomous

Claude Code on Windows breaks without errors: 15 traps I reproduced

Running Claude Code unattended on Windows 11 with Windows PowerShell 5.1, I kept hitting failures that produced no error — just a wrong result. I re-triggered every one of them on my machine (Windows PowerShell 5.1.26100, Python 3.13.7, Claude Code 2.1.304, October 2026).

My machine runs Japanese Windows. For the traps that depend on code pages, I also re-ran the checks with the English defaults (ANSI 1252, OEM 437). Only #9 stopped breaking. The rest either broke the same way, broke differently (noted below), or do not depend on the language setting at all.

To see which of #1–#14 happen on your own machine, run the free script (MIT, also a Claude Code plugin): https://github.com/cart231-ffly-b/claude-code-windows-traps

The map

# What breaks Where you hit it What I saw
1 exit 2 becomes 1 calling a script with powershell -Command -File=2 -Command=1
2 an argument is silently dropped -File with -Path a b count=1, exit code 0
3 an array becomes one string -File with -Path a,b first=a,b
4 non-ASCII arrives as ?? piping text into a native program bytes 3f3f
5 captured output is mojibake reading UTF-8 output with the default console encoding café— read as caf├⌐ΓÇö (cp437)
6 Python crashes only when redirected python x.py > out.txt printing ✓ UnicodeEncodeError, exit 1
7 PYTHONIOENCODING has no effect python -I exit 1 with -I, 0 without
8 an em dash becomes a syntax error non-ASCII .ps1 saved without BOM "string is missing the terminator"
9 a .cmd runs its comments (CJK Windows only) .cmd saved with LF cp932=broken cp65001=ok; fine on 437/1252
10 a one-liner is a syntax error powershell -Command "foreach ($i ...)" from PowerShell exit 1
11 -Include is ignored Get-ChildItem -LiteralPath ... -Include *.ps1 the .md came back too
12 letters vanish into newlines Markdown backticks inside "..." `n became a newline
13 a growing file shows 0 bytes listing a log under AppData listed 0, actual 5,000,000
14 claude -p gets no prompt --allowedTools Read "prompt" Input must be provided ...
15 a slow safety hook lets the write through a PreToolUse hook that answers after its timeout the file was written, 3 times out of 3

Three habits that cover most of them

  1. Measure what the screen won't show. Exit codes, bytes, real file sizes.
  2. ASCII instruction + UTF-8 file. Keep non-ASCII text out of pipes, arguments and "...". Tell Claude: Read the file C:\work\prompt.md and do exactly what it says.
  3. Run it the way it will really run — through the scheduler, with -File — once, before you trust it.

Each trap

1. -Command turns exit code 2 into 1. A script that only does exit 2 returned 2 with -File and 1 with -Command. Codes 0 and 1 pass through unchanged, so nothing looks wrong until you start using 2 or higher — Task Scheduler's "Last Run Result" shows 1 too. Use -File, or append ; exit $LASTEXITCODE.

2–3. -File passes arguments as plain strings. -Path a b silently dropped b (exit code 0). Add [CmdletBinding()] and the same call stops with "A positional parameter cannot be found" — stopping is safer. -Path a,b stays one string a,b; split it yourself with -split ','.

4. Piped non-ASCII text arrives as ??. Windows PowerShell 5.1 encodes text sent to native programs with $OutputEncoding, which defaults to us-ascii. café— piped to Python arrived as caf??. Prompts piped into claude -p get damaged the same way. Put long prompts in a UTF-8 file and send an ASCII instruction instead.

5. Captured output turns into mojibake. The reverse direction breaks too: UTF-8 output read with the default console encoding became unrelated characters — café— came back as caf├⌐ΓÇö under cp437 (the US default). Set [Console]::OutputEncoding to UTF-8 on the reading side, and align the sending side as well.

6. Python crashes only when redirected. On screen, Windows Python prints anything. Redirected to a file, it encodes with the ANSI code page and crashes on any character outside it. With cp1252, — and é were fine, but ✓ (U+2713) crashed with exit 1 — and AI-written scripts love printing ✓ and →. This is one reason scripts "work by hand but fail under the scheduler". PYTHONIOENCODING=utf-8 fixes it. (Python 3.15, released October 9, makes UTF-8 the default, so on 3.15 or later this is not expected. I tested on 3.13; with -X utf8, the 3.15 default, the same script did not crash.)

7. python -I ignores PYTHONIOENCODING. With -I (isolated mode) the crash stayed (exit 1 with -I, 0 without). Drop -I, or call sys.stdout.reconfigure(encoding="utf-8") inside the script. This one is also not expected on Python 3.15 or later.

8. A BOM-less non-ASCII .ps1. PowerShell 5.1 reads BOM-less files with the ANSI code page. On English Windows that is worse than mojibake: the UTF-8 bytes of — end in 0x94, which cp1252 reads as ” — and PowerShell treats curly quotes as real quotes. Write-Output "a—b" saved without BOM, read as cp1252, fails to parse ("The string is missing the terminator"). Save such files as UTF-8 with BOM, or keep .ps1 files ASCII-only.

9. (Japanese, Chinese and Korean Windows only) A .cmd with LF line endings runs its comments. AI file tools usually write LF. A .cmd with non-ASCII rem comments, saved with LF, made cmd.exe try to execute the comment text. The same file broke under code page 932 and ran to the end under 65001 (UTF-8). Under 437 and 1252, a file with accented Latin comments ran fine. If your users include CJK Windows, save .cmd files with CRLF anyway.

10. A one-liner becomes a syntax error. From PowerShell, powershell -Command "foreach ($i in 1..2) { $i }" lets the calling shell expand $i (to nothing) first. The child receives foreach ( in 1..2) and exits with 1. Put the logic in a .ps1 and run it with -File.

11. -Include is ignored with -LiteralPath. In a folder with one .ps1 and one .md, Get-ChildItem -LiteralPath <dir> -Recurse -File -Include *.ps1 returned both. My own health-check script hit this and flagged Markdown and JSON files as broken batch files — my test fixtures only contained scripts, so the tests never showed it. Filter extensions with Where-Object.

12. Backticks inside "...". Inside a double-quoted PowerShell string the backtick is an escape character: Markdown like `night-shift` turns `n into a newline and the letter disappears. Use single-quoted here-strings for text that contains backticks.

13. A file being written shows 0 bytes. A log being written by a background process listed as 0 bytes in Get-ChildItem; opened, it held 5,000,000 bytes. On my machine this happened every time under AppData and not under my home folder; I have not confirmed why. Open the file before concluding it is empty.

14. claude -p swallows the prompt. claude -p --allowedTools Read "say hi" failed with Error: Input must be provided either through stdin or as a prompt argument when using --print. --allowedTools and --add-dir take any number of values, so they eat the prompt. Send the prompt on stdin.

15. A safety hook that answers late lets the write through. I made a PreToolUse hook that always denies, but waits 15 seconds first, with a 3-second timeout. Claude Code wrote the file anyway — no error, no warning, three runs out of three. With a 60-second timeout it was blocked. The official hooks reference says the same thing: a timed-out PreToolUse hook does not block the call, so don't count on a stalled hook as a gate. The fix is one line: add "onFailure": "block" to the hook (Claude Code 2.1.295 or later). With it, the same late hook blocked the write, and so did a hook whose script was missing.


I packaged the fixes as cc-win-kit: a write guard for Claude Code (with onFailure: "block"), an unattended runner with stop conditions, a doctor that finds these files and fail-open hook settings on your machine, and a script that shows the hook-timeout hole with the real claude -p. It's $19: https://payhip.com/b/bRnDJ (the trap reproduction script itself is the free one above)

Disclosure: this post was written with AI assistance. Claude Code ran the reproduction scripts on my Windows machine and drafted the text; the results quoted above come from those runs.

Top comments (0)