fix: gateway.cmd launcher garbles non-ASCII profile paths on non-CJK Windows locales#108967
Conversation
474a1b4 to
2a6c4a1
Compare
|
Codex review: needs maintainer review before merge. Reviewed July 17, 2026, 3:08 AM ET / 07:08 UTC. Summary PR surface: Source +95, Tests +202. Total +297 across 10 files. Reproducibility: yes. The PR supplies a concrete current-main failure and successful after-fix run on a real Turkish Windows 11 host where ACP 1254 differs from OEMCP 857. Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the OEM-aware encoder with explicit Do we have a high-confidence way to reproduce the issue? Yes. The PR supplies a concrete current-main failure and successful after-fix run on a real Turkish Windows 11 host where ACP 1254 differs from OEMCP 857. Is this the best way to solve the issue? Yes. Encoding the installer-resolved paths for the console's actual OEM page preserves custom prefixes and portable Node layouts, while environment-variable substitution would create incorrect path assumptions. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against d78396124eb6. Label changesLabel justifications:
Evidence reviewedPR surface: Source +95, Tests +202. Total +297 across 10 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (7 earlier review cycles)
|
2a6c4a1 to
28b40b8
Compare
28b40b8 to
6502b2a
Compare
537c810 to
44b713b
Compare
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix: gateway.cmd launcher garbles non-ASCII profile paths on non-CJK Windows locales This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
b6cefa9 to
1c0b82e
Compare
The launcher encoder now resolves the boot-time OEM code page via resolveWindowsOemEncoding, leaving resolveWindowsSystemEncoding with no external importers; the dead-export ratchet (knip all-exports) fails CI on exported-but-module-local functions.
1c0b82e to
400fb82
Compare
|
Maintainer proof for head
Review artifacts validated with recommendation |
|
Merged via squash.
|
…Windows locales (openclaw#108967) * fix(daemon): encode Windows cmd launcher to the console OEM code page * fix(infra): unexport resolveWindowsSystemEncoding The launcher encoder now resolves the boot-time OEM code page via resolveWindowsOemEncoding, leaving resolveWindowsSystemEncoding with no external importers; the dead-export ratchet (knip all-exports) fails CI on exported-but-module-local functions. * test(windows): cover OEM launcher encoding resolver * fix(windows): declare launcher OEM code page * fix(windows): fail closed on unsupported OEM pages * fix(windows): reject CP1258 precomposition drift * fix(windows): guard CP864 launcher syntax * test(windows): pin OEM launcher code page --------- Co-authored-by: Peter Steinberger <[email protected]>
Closes #108774
What Problem This Solves
Fixes an issue where Windows users whose profile path contains non-ASCII characters outside the CJK range (Turkish, Cyrillic, Greek, Western European accents, ...) can install OpenClaw but the managed Gateway never starts: the generated
gateway.cmdlauncher garbles the profile path and the launch chain dies with "The system cannot find the path specified" /MODULE_NOT_FOUND.#107751 fixed this failure for CJK locales by encoding the launcher in the system ANSI code page — but only on locales where ANSI == OEM, and it deliberately left windows-125x hosts on plain UTF-8 ("ANSI bytes would just be a different flavor of wrong there"). On those hosts (e.g. Turkish: ANSI 1254, OEM 857) cmd.exe still reads the UTF-8 launcher in its OEM code page and the mojibake from #108774 persists.
Why This Change Was Made
cmd.exe parses batch files with the console code page, which a fresh console (Task Scheduler, Startup folder, double-click) initializes from the boot-time registry
OEMCP— not from the ANSI page, and not from whatever a parent session lastchcp'd to. So the launcher encoder now targets the OEM page directly instead of approximating it via ANSI:resolveWindowsOemEncoding()(new,src/infra/windows-encoding.ts) readsHKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCPonce (cached) through a narrowqueryWindowsRegistryValueexport that reuses the existing reg.exe query logic insrc/infra/windows-install-roots.ts.encodeWindowsLauncherScript(src/infra/windows-launcher-encoding.ts) encodes non-ASCII.cmdcontent to that OEM page with the same@rem openclaw-launcher-encoding=<label>marker and fail-closed round-trip verification introduced in fix(daemon): gateway fails to launch on Windows when the profile path contains CJK characters #107751. TheCMD_ANSI_EQUALS_OEM_ENCODINGSspecial case is deleted: on CJK locales OEMCP == ACP, so those hosts resolve the identical labels (gbk/big5/shift_jis/euc-kr/windows-874) and produce byte-identical launchers — no behavior change there.cp###labels; iconv-lite 0.7.2 is already a root dependency since fix(daemon): gateway fails to launch on Windows when the profile path contains CJK characters #107751).gb18030-marked files).Design notes:
%APPDATA%/%ProgramFiles%substitution (the issue's suggested fix): the ClawSweeper review on Bug: gateway.cmd breaks with non-ASCII Windows usernames (mojibake) #108774 correctly notes that would break custom npm prefixes, portable Node, and version managers. This fix keeps the installer-resolved paths and makes the encoding correct instead.TextDecoderwhere its tables match Windows (gbk/big5/shift_jis/windows-874 — it also flags best-fit hazards like shift_jis¥→ 0x5C); iconv's own decode for euc-kr (Node ICU is KS X 1001-only and false-rejects cp949/UHC extension syllables) and for allcp###pages (no WHATWG decoder exists; WHATWGibm866even disagrees with Windows CP866 at 0x1A/0x1C/0x7F). Safe because iconv-lite never best-fits — unmappable characters become?and fail the round-trip, aborting the install with the existing clear error.0x25 "%", which generated cmd scripts contain, and the corruption would round-trip cleanly through iconv's own model — modern Arabic Windows uses OEM 720 (included) anyway. CP1258 (Vietnamese, the one locale whose OEMCP is a windows-125x page) is omitted because iconv-lite cannot round-trip Vietnamese combining forms; it keeps today's UTF-8 fallback instead of turning mojibake into a hard install error. Hosts with the "UTF-8 worldwide" beta (OEMCP 65001) keep plain UTF-8, which is correct there.User Impact
openclaw gateway install+gateway startnow works for Windows accounts with Turkish/Cyrillic/Greek/Western-European/etc. non-ASCII usernames — previously the P0 release-blocker path in #108774. CJK users see byte-identical output to #107751. ASCII-only installs are untouched (encoder still short-circuits before any code-page probe).Evidence
Live before/after on a real affected host — Windows 11 Pro, Turkish locale (registry ACP 1254 / OEMCP 857), i.e. exactly the ANSI≠OEM case #107751 left open. A launcher with
buildTaskScript-shaped content (cd /d,set "OPENCLAW_STATE_DIR=...", node invocation) pointing into a...\ev-yiğit-öğün\profile directory, executed under a CP857 console (what Task Scheduler provides):Before (bytes exactly as origin/main writes them on this host — UTF-8 fallback):
After (bytes from the fixed
encodeWindowsLauncherScript(), real production function + real registry read, which resolvedcp857and emitted the@rem openclaw-launcher-encoding=cp857marker):Tests (all pass,
node scripts/run-vitest.mjs ...):src/infra/windows-launcher-encoding.test.ts,src/infra/windows-encoding.test.ts,src/daemon/schtasks.test.ts,src/daemon/schtasks.install.test.ts,src/infra/windows-task-restart.test.ts— 49 tests. New regression cases: cp857 Turkish path round-trip with marker, cp850 Western European, OEMCP-65001 stays UTF-8, unrepresentable characters on a single-byte OEM page fail the install fail-closed. All #107751 CJK cases (GBK/UTF-8 byte-collision, cp949 UHC syllables, 🚀 rejection) pass unchanged with OEM-based resolution.oxfmtandoxlintclean on all touched files;tsgo -p tsconfig.core.jsonreports no errors in touched files (the 42 pre-existing errors on this machine reproduce identically on a cleanorigin/maincheckout — local env, unrelated).