Windows: non-ASCII file paths corrupted (surrogate-escaped) when passed to PreToolUse Python hooks
Summary
On Windows (CP1252 locale), when an Edit targets a file whose path contains non-ASCII characters (accented letters, em-dash), the path delivered to a PreToolUse Python hook is mojibake / surrogate-escaped. A hook that compares the incoming path to its own state (e.g. an "edit-after-read" guard) can never match the real file and blocks the edit permanently.
Observed
- File path:
...\2026-06-29 — CRÍTICA — coherence-refinery ...md - Hook received:
...\2026-06-29 — CR<?>\udc8dTICA — coherence-refinery ...md - The
Í(U+00CD) arrives as a lone UTF-16 surrogate (\udc8d) / Pythonsurrogateescapeof CP1252 bytes, not the real character. - Re-reading the file via the Read tool does NOT clear the guard — the path the hook sees never equals the path Read recorded.
Root cause (hypothesis)
The path is passed to the hook subprocess decoded with the wrong codec on Windows (CP1252 bytes interpreted with errors="surrogateescape") instead of UTF-8, so the hook string cannot round-trip to the real filename.
Reproduction
- Windows, CP1252 locale. Create a file with a non-ASCII name (e.g. accents + em-dash).
- Configure a trivial PreToolUse Edit hook that prints the path it receives.
- Read then Edit the file -> the path arrives mangled (surrogate-escaped), not UTF-8.
Impact
Any user with non-ASCII filenames (common in pt-BR) + a path-comparing Edit hook is hard-blocked from editing those files. Workaround: use the Write tool (overwrite) instead of Edit.
Suggested fix
Ensure file paths passed to hooks are UTF-8 end-to-end (e.g. PYTHONUTF8=1 / encoding="utf-8" for hook subprocesses on Windows, or pass paths as UTF-8 JSON).
Environment
- OS: Windows 11, Git Bash, CP1252 locale
- Claude Code CLI