jdx/mise · error
cannot write Windows launcher because
Error message
cannot write Windows launcher because {} is not a generated launcher What it means
In `mise generate tool-stub` on Windows, mise writes a companion Windows launcher file. If the launcher path already exists as a regular file but its content fails the `is_generated_launcher` check, mise bails with this error rather than overwriting a file it did not generate. This prevents overwriting user files that happen to occupy the launcher path.
Solutions
- Remove or rename the existing file at the launcher path and re-run generation
- Inspect the file's content; if it's a stale mise launcher, delete it so a fresh one is written
- Generate into a clean dedicated output path
Example fix
// before: custom script occupies launcher path stubs\tool.cmd # user-written, not generated -> bail // after mv stubs\tool.cmd .\scripts\ mise generate tool-stub --url https://example.com/tool
Defensive patterns
Strategy: validation
Validate before calling
if (fs.existsSync(launcherPath) && fs.lstatSync(launcherPath).isFile()) {
const content = fs.readFileSync(launcherPath, 'utf8');
if (!content.includes('generated by mise')) throw new Error('non-generated file at launcher path');
} Try / catch
try {
await exec('mise generate tool-stub ...');
} catch (e) {
if (String(e).includes('is not a generated launcher')) {
fs.renameSync(launcherPath, launcherPath + '.bak');
await exec('mise generate tool-stub ...');
}
} Prevention
- Keep launcher paths free of user scripts and third-party files
- Regenerate launcher-occupied stub dirs from the same mise version
- Inspect unknown files at launcher paths before deleting them
When it happens
Trigger: Running `mise generate tool-stub` where the computed Windows launcher path exists as a regular file whose content is not a mise-generated launcher — e.g. a user-created script, a downloaded binary, or a launcher from another tool.
Common situations: Users placed their own script at the launcher path; stubs were generated into a directory shared with other tools; an older mise's launcher format no longer matches the current generated marker.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- cannot write Windows launcher because
- cannot write Windows launcher because
- cannot replace task stub directory because
- brew-cask prune is not supported on windows
- brew import is not supported on windows
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/40b086e57ff3f393.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/generate/tool_stub.rs:237
Ok(None)
}
/// Refuse to replace a `.cmd` beside the stub that mise did not write.
///
/// `--output` is the user's choice, so `<stub>.cmd` is a name a project may already be using
/// for a script of its own, and nothing about that name says mise owns it. The stub itself is
/// different: the user named it, so overwriting it is what they asked for.
fn validate_windows_launcher(&self, stub_content: &str) -> Result<()> {
if !wants_windows_launcher(stub_content) {
return Ok(());
}
let Some(launcher) = super::windows_launcher_path(&self.output) else {
return Ok(());
};
match fs::symlink_metadata(&launcher) {
Ok(metadata) if metadata.file_type().is_file() => {
if !super::is_generated_launcher(&file::read_to_string(&launcher)?) {
bail!(
"cannot write Windows launcher because {} is not a generated launcher",
display_path(&launcher)
);
}
}
Ok(_) => bail!(
"cannot write Windows launcher because {} is not a regular file",
display_path(&launcher)
),
Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}
Err(err) => return Err(err.into()),
}
Ok(())
}
fn get_tool_name(&self) -> String {
self.output
.file_name()View on GitHub (pinned to 533346cc37)