jdx/mise · error
cannot replace task stub directory because
Error message
cannot replace task stub directory because {} is not a generated task stub What it means
During stub-tree validation, mise treats executable-extension files as native launchers it generated, and confirms ownership via `Launchers::owns`. If an `.exe`/executable-named file in the stub directory was not created by mise (not in its launcher registry), mise refuses to replace the directory with this error.
Solutions
- Move the foreign executable out of the stub directory
- Delete the stale/unowned launcher file
- Point `mise generate task-stub` at a dedicated output directory that only contains generated stubs
Example fix
// before: user's own tool.exe sits in stubs\ stubs\tool.exe # not owned by mise -> bail // after mv stubs\tool.exe .\tools\ mise generate task-stub --output stubs
Defensive patterns
Strategy: validation
Validate before calling
const foreignExe = fs.readdirSync(stubDir) .filter(f => /\.(exe|cmd|bat)$/i.test(f)) .filter(f => !generatedLauncherRegistry.includes(f));
Try / catch
try {
await exec('mise generate task-stub ...');
} catch (e) {
if (String(e).includes('is not a generated task stub')) {
// move foreign executables out of stubDir, then retry
}
} Prevention
- Keep user binaries outside mise stub output directories
- Regenerate stubs from the same mise version that owns the launchers
- Use one output directory exclusively for generated stubs
When it happens
Trigger: Running `mise generate task-stub` against a directory containing a file with an executable extension (e.g. `.exe`) that is not tracked as a mise-generated launcher — a user-placed binary or a stale launcher from a removed output path.
Common situations: Users copied real tools/binaries into the stub directory; launcher registry reset (path moved) so previously generated launchers are no longer owned; shared bin directory pointed at as output.
Related errors
- cannot replace task stub directory because
- cannot replace task stub directory because
- cannot write Windows launcher because
- cannot write Windows launcher because
- cannot write Windows launcher because
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/5cac063825432e6f.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/generate/task_stubs.rs:647
for entry in fs::read_dir(path)? {
let entry = entry?;
let entry_path = entry.path();
let metadata = fs::symlink_metadata(&entry_path)?;
if metadata.file_type().is_dir() {
let child_files = validate_generated_stub_tree(&entry_path, launchers)?;
if child_files == 0 {
bail!(
"cannot replace task stub directory because {} is empty",
display_path(&entry_path)
);
}
files += child_files;
} else if metadata.file_type().is_file() && is_exe_path(&entry_path) {
// A native launcher of ours. Checked before anything reads the file as text, which a
// binary is not. Not counted towards `files`, same as the `.cmd`: a directory holding
// nothing but launchers has no stubs left and should still be reported as empty.
if !launchers.owns(&entry_path) {
bail!(
"cannot replace task stub directory because {} is not a generated task stub",
display_path(&entry_path)
);
}
} else if metadata.file_type().is_file()
&& is_generated_task_stub(&file::read_to_string(&entry_path)?)
{
files += 1;
} else if metadata.file_type().is_file()
&& super::is_generated_launcher(&file::read_to_string(&entry_path)?)
{
// Our own Windows launcher. Not counted towards `files`: a directory holding nothing
// but launchers has no stubs left and should still be reported as empty.
} else {
bail!(
"cannot replace task stub directory because {} is not a generated task stub",
display_path(&entry_path)
);View on GitHub (pinned to 533346cc37)