jdx/mise · error
--localized-dir {raw:?} cannot be carried to Windows: {bad:?
Error message
--localized-dir {raw:?} cannot be carried to Windows: {bad:?} is not allowed in a path component there, so the generated launcher could not create the directory. Drop --windows, or pick a name Windows accepts. What it means
With `--localize`, `mise generate bootstrap --windows` embeds --localized-dir into a .cmd launcher that mkdir's it (relative dirs are joined to %project_dir%). Windows forbids < > : " | ? * inside a path component — and a component like `C:foo` is drive-relative there, not a path — so the generator refuses the value rather than emitting a launcher that would fail later on the contributor's Windows machine.
Source
Thrown at src/cli/generate/bootstrap.rs:242
rest.trim_start_matches(['\\', '/'])
}
/// The `localized_dir` value for the batch script — the same two rules the bash branch applies:
/// escape the value, and join it to the project directory only when it is relative.
///
/// Refuses a value Windows could not hold rather than emitting one. A directory named `C:foo` is
/// ordinary on Linux and the bash half installs into it happily, but on Windows `C:foo` is
/// drive-*relative*, so `%project_dir%\C:foo` is not a path at all and `mkdir` fails — on the
/// contributor's machine, not on the machine that generated the file. Calling it rooted instead
/// would be worse: that drops `%project_dir%\` and installs wherever cmd's per-drive working
/// directory happens to point, silently diverging from the bash half.
fn windows_localized_dir(dir: &Path) -> Result<String> {
let raw = dir.to_string_lossy();
if let Some(bad) = windows_path_components(&raw)
.chars()
.find(|c| WINDOWS_FORBIDDEN_IN_COMPONENT.contains(c))
{
bail!(
"--localized-dir {raw:?} cannot be carried to Windows: {bad:?} is not allowed in a \
path component there, so the generated launcher could not create the directory. \
Drop --windows, or pick a name Windows accepts."
);
}
let escaped = cmd_escape(&raw);
match is_windows_absolute(&escaped) {
true => Ok(escaped),
false => Ok(format!(r"%project_dir%\{escaped}")),
}
}
/// Escape a value for interpolation into a `set "var=…"` line in the launcher.
///
/// Only `%` needs it. The script keeps delayed expansion off, so `!` is already an ordinary
/// character there — measured: with it off, `set "d=…\p6-od!d"` followed by `mkdir "%d%"` creates
/// `p6-od!d`, and with it on the same two lines create `p6-odd`. A raw `%` would still be read at
/// parse time, so with `x` set a directory named `my%x%dir` becomes `myCLOBBEREDdir`.View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Pick a --localized-dir whose components avoid < > : " | ? * (e.g. .mise-local, cache-dev)
- Drop `--windows` to generate only the bash bootstrap, which accepts the Unix-legal name
- Keep the odd name for the Unix script and generate the Windows launcher separately with a Windows-safe directory
Example fix
# before mise generate bootstrap --localize --localized-dir 'cache:dev' --windows # error: ':' is not allowed in a path component there # after mise generate bootstrap --localize --localized-dir 'cache-dev' --windows
Defensive patterns
Strategy: validation
Validate before calling
#!/bin/bash # reject Windows-forbidden chars before generating if printf %s "$LOCALIZED_DIR" | grep -q '[<>:"|?*]'; then echo "--localized-dir '$LOCALIZED_DIR' cannot be carried to Windows" >&2 exit 1 fi mise generate bootstrap --localize --localized-dir "$LOCALIZED_DIR" --windows
Type guard
windows_safe_dir() {
# returns 0 when every component avoids < > : " | ? *
case "$1" in
*[\<\>:\"\|\?*]*) return 1 ;;
*) return 0 ;;
esac
} Prevention
- Constrain --localized-dir to [A-Za-z0-9._-] when generating cross-platform bootstraps
- Remember a leading drive prefix (C:foo) is drive-relative on Windows — avoid colons entirely
- Generate the Windows variant in CI from a fixed, reviewed constant rather than dynamic input
When it happens
Trigger: `mise generate bootstrap --localize --localized-dir <dir> --windows` where any component of <dir> contains one of the seven forbidden characters (a colon is the common trap: names like `C:foo` or `cache:dev` are legal on Linux/macOS but unusable on Windows).
Common situations: Unix project localizing into a timestamp/URL-derived name containing colons (`backup:2026`, `https://` fragments); passing a drive-relative Windows path by mistake; script composing the dir from unvalidated input.
Related errors
- cannot write Windows launcher because {} is not a generated
- cannot write Windows launcher because {} is not a regular fi
- cannot write Windows launcher because {} is not a generated
- cannot write Windows launcher because {} is not a regular fi
- bootstrap user '{name}' {field} must be an absolute path
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/be7a6086857d838e.
Report an issue: GitHub.