jdx/mise · error
cannot replace task stub directory because
Error message
cannot replace task stub directory because {} is empty What it means
When validating a stub directory tree before replacement, mise recursively counts generated stub files. If a subdirectory contains no countable generated stubs at all (it is empty or holds only launchers, which are not counted), mise bails with this error rather than deleting an empty directory during replacement.
Solutions
- Delete the empty subdirectory before re-running generation
- Place a valid generated task stub in the subdirectory
- Regenerate into a fresh output directory
Example fix
// before: stubs\nested\ exists but is empty mkdir -p stubs\nested mise generate task-stub --output stubs # fails // after rmdir stubs\nested mise generate task-stub --output stubs
Defensive patterns
Strategy: validation
Validate before calling
const hasEmptySubdir = (dir: string): boolean =>
fs.readdirSync(dir, { withFileTypes: true, recursive: true })
.some(d => d.isDirectory() && fs.readdirSync(path.join(d.parentPath ?? dir, d.name)).length === 0); Try / catch
try {
await exec('mise generate task-stub ...');
} catch (e) {
if (String(e).includes('is empty')) {
// remove empty subdirectories then retry
await exec('find ' + stubDir + ' -type d -empty -delete');
await exec('mise generate task-stub ...');
}
} Prevention
- Delete empty subfolders from stub output directories before regenerating
- Never leave launcher-only directories when cleaning stubs
- Regenerate into a fresh directory instead of mutating a partially-cleaned tree
When it happens
Trigger: Running `mise generate task-stub` against an output directory containing an empty subdirectory, or a subdirectory whose only files are Windows launchers/`.cmd` files (explicitly excluded from the stub count).
Common situations: User manually cleaned out a subfolder of stubs but left the folder; a previous partial generation left a launcher-only directory; git checkout or sync tooling pruned stub files but kept directories.
Related errors
- cannot replace task stub directory because
- cannot replace task stub directory because
- invalid tool path : extended-length and device paths (\\?\…
- scheduled task name contains characters that cannot be…
- Windows script file name
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/4a67845ed48b674e.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/generate/task_stubs.rs:636
display_path(path),
task.display_name
),
}
validate_generated_stub_tree(path, launchers)?;
Ok(())
}
fn validate_generated_stub_tree(path: &Path, launchers: &Launchers) -> Result<usize> {
let mut files = 0;
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)?)
{View on GitHub (pinned to 533346cc37)