Skip to content

feat(env): warn when PATH is long enough for cmd.exe to ignore - #11643

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:feat/warn-windows-path-limit
Aug 3, 2026
Merged

feat(env): warn when PATH is long enough for cmd.exe to ignore#11643
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:feat/warn-windows-path-limit

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Draft — the detection is straightforward, but where it should fire and how loudly is your call. #5830's fifth suggestion, and the only one of that thread's eight that does not need a design decision first.

What breaks, measured

Past 8191 characters cmd.exe does not truncate an inherited variable — it drops it. Nothing on PATH resolves, so npm, npx and batch scripts report that every command is unrecognised, with nothing naming PATH, cmd.exe or mise.

Windows 11 26200 / cmd 10.0.26100.8875, same PATH for both columns, Git\cmd appended last:

Path length where.exe where git --version
2024 OK OK
8184 OK OK
8239 OK not recognized
30019 OK not recognized

(The where.exe column is there because it is the probe docs/troubleshooting.md currently recommends, and it never discriminates — where.exe is in System32, which cmd.exe resolves while ignoring PATH. #11642 fixes that separately.)

KB 830473 documents the behaviour, but its "Applies to" stops at Windows 7 / Server 2008 R2 / 2012 R2 and hedges with "as appropriate to the operating system" — hence the measurement above rather than a citation alone.

Where it fires

Two surfaces can reach that length, and they do not share a code path:

  • PathEnv::join — every environment mise computes: mise x/run children, mise env, backends, core plugins.
  • hook_env.rs — assembles the shell's PATH by hand with join_paths(pre + user_paths + tool_paths + post + post_user), so PathEnv::join's check never sees it. This is the copy a tool started directly from an activated shell inherits, which is the reported symptom (npm install from a normal prompt), so leaving it out would miss the main case.

warn_once! rather than hint!: hints require console::user_attended() and so never appear in scripts or CI, and are suppressed permanently after one appearance. A broken environment should be reported every process.

Correctness details

  • The predicate is pure and takes a length, so the boundary is unit-tested on every platform, including the windows-unit job, and cfg!(windows) inside it means it can never fire elsewhere.
  • Length is counted in UTF-16 code units, which is what Windows counts. OsStr::len would return WTF-8 bytes and treat a three-byte character as three, warning about a PATH cmd.exe accepts. Pinned by a test.

This only reports the condition. It does not shorten anything — a large enough toolset still hits the limit, and the structural proposals in #5830 (shorter install dirs, hashed paths, a per-project shim dir) are untouched.

Open questions — why this is a draft

  1. Suppression. Someone sitting near the limit sees this on every process. Keep a plain warning, or add a disable_hints-style setting?
  2. hook-env. It is the surface that matters most and also the noisiest — re-evaluated on every prompt, where per-invocation suppression buys little.
  3. A second threshold at 32767? Past the Win32 per-variable limit, CreateProcess fails outright with "not enough memory resources" — also measured. Louder failure, equally opaque cause. Worth catching here too, or out of scope?
  4. Tests. Unit tests cover the boundary. An end-to-end check belongs in e2e-win/run.ps1 (build a long PATH, run mise x, assert the warning) — happy to add it once the above are settled, rather than write it against a shape that may change.

Summary by CodeRabbit

  • Bug Fixes
    • Added warnings when commands launched from an activated shell may not receive generated PATH updates.
    • Added detection for Windows Command Prompt PATH values exceeding supported length limits.
    • Improved PATH length measurement for Unicode characters.
    • Added checks for externally configured PATH values.
    • Clarified when PATH settings may be ignored or require adjustment.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change detects Windows cmd.exe PATH values over 8191 UTF-16 code units. It warns when PathEnv or shell hook logic constructs an oversized PATH. Tests cover boundaries, non-Windows behavior, and Unicode lengths.

Changes

PATH limit warning

Layer / File(s) Summary
PATH length detection and validation
src/path_env.rs
Adds UTF-16 PATH measurement, the Windows limit predicate, one-time warning logic, an external string wrapper, and boundary tests.
PATH warning integration
src/path_env.rs, src/cli/hook_env.rs
Checks joined PATH values and shell hook PATH values for possible cmd.exe truncation or ignoring.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • jdx/mise#11642: Documents troubleshooting for Windows cmd.exe PATH-limit violations.

Poem

A rabbit counts each PATH byte wide,
UTF-16 units side by side.
When cmd.exe may ignore the way,
A warning hops into the day.
Boundary tests keep counts in line.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the added warning for PATH lengths that cause cmd.exe to ignore the PATH.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/path_env.rs (1)

185-202: 🧹 Nitpick | 🔵 Trivial

Align the warning message with the current lifetime.

warn_once! keys on the fully interpolated msg, and warn_if_cmd_ignores_path_str() is called by hook-env, which runs as a new process on each shell render. If the process starts once per prompt, change the doc comment from “warn once per process” to “warn once per invocation” unless the behavior is changed to persist the coarser key across activation iterations.

If PATH lengths change between the PathEnv join and the manual hook PATH, the warning can still happen twice in the same process because the interpolated message differs. Use a stable key if that deduplication is intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/path_env.rs` around lines 185 - 202, Update the documentation above
warn_if_cmd_ignores_path to say the warning occurs once per invocation, matching
hook-env’s process lifetime. In warn_if_cmd_ignores_path, use a stable
warn_once! deduplication key rather than the fully interpolated message if
warnings must remain deduplicated when PATH lengths differ within one process;
preserve the existing diagnostic text and length values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/path_env.rs`:
- Around line 185-202: Update the documentation above warn_if_cmd_ignores_path
to say the warning occurs once per invocation, matching hook-env’s process
lifetime. In warn_if_cmd_ignores_path, use a stable warn_once! deduplication key
rather than the fully interpolated message if warnings must remain deduplicated
when PATH lengths differ within one process; preserve the existing diagnostic
text and length values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: f0b16f48-4d7c-4f3b-9fb8-e8bc3d21a156

📥 Commits

Reviewing files that changed from the base of the PR and between e5230aa and ca93282.

📒 Files selected for processing (2)
  • src/cli/hook_env.rs
  • src/path_env.rs

@JamBalaya56562
JamBalaya56562 force-pushed the feat/warn-windows-path-limit branch from ca93282 to f95c26a Compare August 2, 2026 14:53
Past 8191 characters cmd.exe drops an inherited environment variable entirely
rather than truncating it, so every command run through it reports "is not
recognized" with nothing naming PATH, cmd.exe or mise.

Checked on both surfaces that can reach that length: PathEnv::join, which every
computed child environment goes through, and hook-env's hand-assembled PATH,
which is the copy a tool started directly from an activated shell inherits.

The predicate is pure and counts UTF-16 code units the way Windows does, so the
boundary is unit-testable on every platform and cannot fire off Windows.

This only reports the condition — it does not lower the ceiling.

Reported in jdx#5830
@JamBalaya56562
JamBalaya56562 force-pushed the feat/warn-windows-path-limit branch from f95c26a to ab5ab87 Compare August 2, 2026 14:56
@JamBalaya56562

Copy link
Copy Markdown
Contributor Author

Both halves taken.

The double warning is real, and it is the common path rather than an edge case. One mise hook-env run measures two PATHs: ts.env_with_path_and_split goes through PathEnv::join, and then hook-env assembles the shell's own PATH by hand. Those are different lengths, so keying warn_once! on the formatted message reports the same problem twice on the surface that is already the noisiest. Now keyed on the condition:

static WARNED_CMD_PATH_LIMIT: AtomicBool = AtomicBool::new(false);
...
if WARNED_CMD_PATH_LIMIT.swap(true, Ordering::Relaxed) {
    return;
}

That removes the first of the open questions in the description, so I have edited it out.

"once per process" was accurate and reassuring in the wrong way, since under mise activate the process is a fresh one on every prompt. Reworded to say what actually happens rather than leaving the reader to work it out:

At most once per invocation, which is not once per user-visible event: under mise activate, hook-env is a fresh process on every prompt, so a PATH left over the limit warns on every prompt. Whether that is the right cadence is an open question on this PR.

That cadence is still the thing I most want a decision on — the guard above makes it one warning per prompt instead of two, which is an improvement rather than an answer.

While in there I also corrected the constant's doc comment, which claimed "nothing on PATH resolves and every command reports is not recognized". Programs in the system directory keep working, because cmd.exe finds those without consulting PATH — the same overclaim reviewers caught in #11642, and the reason the probe documented there never failed.

@JamBalaya56562
JamBalaya56562 marked this pull request as ready for review August 2, 2026 22:16
@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds Windows-specific diagnostics when a generated PATH exceeds cmd.exe's 8191 UTF-16-code-unit limit.

  • Checks both generic PathEnv::join results and the independently assembled activated-shell PATH.
  • Deduplicates warnings within each mise invocation.
  • Adds platform-neutral unit coverage for the threshold and Unicode length calculation.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code failure identified.

The warning is Windows-gated, measures the relevant UTF-16 length, covers both PATH construction paths, and remains separate from the shell commands emitted on stdout.

Important Files Changed

Filename Overview
src/path_env.rs Adds UTF-16 PATH-length measurement, Windows threshold detection, per-process warning deduplication, and boundary tests without an identified actionable defect.
src/cli/hook_env.rs Checks the separately assembled shell PATH before emitting its environment operation; diagnostics remain on stderr and do not contaminate evaluated shell output.

Reviews (1): Last reviewed commit: "feat(env): warn when PATH is long enough..." | Re-trigger Greptile

@jdx
jdx merged commit 300c06c into jdx:main Aug 3, 2026
29 checks passed
donbeave pushed a commit to donbeave/mise that referenced this pull request Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants