Windows: non-ASCII file paths corrupted (surrogate-escaped) when passed to PreToolUse Python hooks

Open 💬 0 comments Opened Jun 30, 2026 by SPA-2026

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) / Python surrogateescape of 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

  1. Windows, CP1252 locale. Create a file with a non-ASCII name (e.g. accents + em-dash).
  2. Configure a trivial PreToolUse Edit hook that prints the path it receives.
  3. 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

View original on GitHub ↗