fix(install): write apm.cmd shim as ASCII (cmd.exe cannot parse UTF-16LE)#1522
Merged
danielmeppiel merged 1 commit intoMay 27, 2026
Merged
Conversation
…6LE) PR #1512 switched the Windows shim encoding to UTF-16LE with BOM on the assumption that cmd.exe auto-detects the encoding via the BOM. The Windows CI 'Test install.ps1 end-to-end' job in run 26541947119 proves that assumption wrong: invoking apm.cmd via cmd /c surfaces as garbled output ('D:\a\apm\apm>$@') and exit code 1. cmd.exe parses .cmd files through the system OEM/ANSI code page when they are invoked from PATH; the BOM is not enough to flip it into UTF-16 mode. Fix: write the shim as ASCII. The %LOCALAPPDATA% literal token from #1509 keeps the embedded shim target ASCII-only even when the user's profile directory contains non-ASCII characters, so the original #1509 motivation for a non-ASCII-safe encoding no longer applies for the default install location. Custom APM_INSTALL_DIR roots with non-ASCII paths fall outside this contract (and were not exercised by the prior tests either) -- the percent-escape and absolute-path fallback in the else branch are preserved. Also relax the E2E PowerShell assertion 'Shim points into per-user releases dir': on GitHub Windows runners the temp prefix lives under %LOCALAPPDATA%, so the if-branch is taken and the shim text contains the %LOCALAPPDATA% token rather than the expanded path. Accept either form. Regression tests updated: - test_shim_not_written_with_utf16_encoding (new trap) - test_shim_written_with_ascii_encoding (positive assertion) - removed test_shim_uses_utf16le_with_bom_encoding / test_shim_not_written_with_ascii_encoding (inverted contract) Lint chain silent (ruff check + format, pylint R0801, lint-auth-signals.sh). Refs #1509, #1512. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a Windows regression where apm.cmd was written in UTF-16LE (with BOM) and became unreadable by cmd.exe when invoked via PATH. It reverts the shim output to ASCII and updates tests to reflect the corrected encoding and %LOCALAPPDATA% tokenization behavior.
Changes:
- Write
apm.cmdusingSet-Content -Encoding ASCII -NoNewlineto keep the shimcmd.exe-compatible. - Relax the end-to-end Windows install test to accept either expanded or
%LOCALAPPDATA%-tokenized shim targets. - Update the unit regression tests to forbid UTF-16/UTF-8 writers and positively assert ASCII encoding.
Show a summary per file
| File | Description |
|---|---|
install.ps1 |
Switches shim writing back to ASCII and documents why UTF-16 is not reliable for cmd.exe batch parsing. |
scripts/windows/test-install-script.ps1 |
Adjusts E2E assertion to accept tokenized %LOCALAPPDATA% form in shim content. |
tests/unit/install/test_windows_shim_template.py |
Inverts regression contract: forbid UTF-16/UTF-8 writers and require -Encoding ASCII. |
CHANGELOG.md |
Updates the prior Windows shim entry to describe ASCII encoding behavior. |
Copilot's findings
- Files reviewed: 4/4 changed files
- Comments generated: 2
| # Write the shim as ASCII. cmd.exe interprets .cmd files via the system | ||
| # OEM/ANSI code page and does NOT reliably auto-detect UTF-16LE (even | ||
| # with a BOM) when batch files are invoked via PATH or double-click; a | ||
| # UTF-16 shim surfaces as garbled output like ">��@" and exit code 1. |
| ### Fixed | ||
|
|
||
| - `install.ps1` Windows installer now works on accounts whose profile directory contains non-ASCII characters (e.g. an accented username). Previously `apm --version` reported `The system cannot find the path specified.` because the generated `apm.cmd` shim baked in an ASCII-mangled path. The shim now embeds the literal `%LOCALAPPDATA%` token (cmd.exe expands at runtime) when the install root lives under the local profile, is written as UTF-16LE with BOM instead of ASCII, percent-escapes literal `%` characters in custom `APM_INSTALL_DIR` paths, and carries an advisory `REM` so hand-edits do not re-introduce the bug. (closes #1509) (#1512) | ||
| - `install.ps1` Windows installer now works on accounts whose profile directory contains non-ASCII characters (e.g. an accented username). Previously `apm --version` reported `The system cannot find the path specified.` because the generated `apm.cmd` shim baked in an ASCII-mangled path. The shim now embeds the literal `%LOCALAPPDATA%` token (cmd.exe expands at runtime) when the install root lives under the local profile, percent-escapes literal `%` characters in custom `APM_INSTALL_DIR` paths, and carries an advisory `REM` so hand-edits do not re-introduce the bug. The shim is written as ASCII (cmd.exe does not auto-detect UTF-16 .cmd files invoked through PATH, even with a BOM); the `%LOCALAPPDATA%` literal token keeps the embedded target ASCII-safe regardless of the user's profile path encoding. (closes #1509) (#1512) |
This was referenced May 27, 2026
fix(install): strip non-ASCII bytes from install.ps1 (unblocks self-update on cp1252 consoles)
#1523
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
PR #1512 switched the Windows
apm.cmdshim encoding to UTF-16LE with BOM on the assumption that cmd.exe auto-detects UTF-16 via the BOM. The Windows CITest install.ps1 end-to-endjob in run 26541947119 proves that wrong: invokingapm.cmdvia PATH surfaces as garbled output (D:\a\apm\apm>��@) and exit code 1. Revert to ASCII; the%LOCALAPPDATA%literal token from #1509 keeps the embedded target ASCII-only, so the original non-ASCII profile-path bug stays fixed.Problem (WHY)
Three failures on
windows-latestin the post-merge CI for PR #1512:Two root causes:
.cmdfiles through the system OEM/ANSI code page. The BOM bytes (FF FE) and LE-encoded@echo offget interpreted as ANSI and surface as>��@garbage. cmd reports the prompt and exits 1.%LOCALAPPDATA%\Temp\, so the install.ps1 if-branch fires and writes%LOCALAPPDATA%\Temp\...(the token form) instead of the expanded path. The string match fails.Approach (WHAT)
apm.cmdwithSet-Content -Encoding ASCII -NoNewline(the encoding that worked pre-fix(install): use %LOCALAPPDATA% literal in Windows shim (closes #1509) #1512).%LOCALAPPDATA%literal token from [BUG] The system cannot find the path specified. #1509 keeps the embedded shim target ASCII-only even when the user's profile directory contains non-ASCII characters -- so ASCII encoding does NOT re-introduce the [BUG] The system cannot find the path specified. #1509 bug for the default install location.APM_INSTALL_DIRroots with non-ASCII characters fall outside this contract (and were never tested before); the percent-escape and absolute-path fallback in the else branch are preserved as-is.%LOCALAPPDATA%-tokenized form.test_windows_shim_template.py: trap UTF-16/UTF-8 writers, positively require-Encoding ASCII.Implementation (HOW)
install.ps1-- shim write call:scripts/windows/test-install-script.ps1-- accept tokenized form:Validation evidence
tests/unit/install/test_windows_shim_template.pypass locally.ruff check,ruff format --check,pylint R0801,scripts/lint-auth-signals.sh.Test install.ps1 end-to-endjob will run on this PR -- this is the only ground-truth verification for cmd.exe interpretation behavior and is what regressed previously.Trade-offs
APM_INSTALL_DIRroots with non-ASCII paths are not robustly supported. ASCII encoding may strip such characters. This matches pre-fix(install): use %LOCALAPPDATA% literal in Windows shim (closes #1509) #1512 behavior; the case was never tested. Users hitting it should setAPM_INSTALL_DIRto an ASCII path or rely on the default%LOCALAPPDATA%location.[System.Text.Encoding]::GetEncoding(0)), which differs between Windows PowerShell and PowerShell Core. Out of scope for this fix.Refs #1509, #1512.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com