jdx/mise · error
cannot write task stub because
Error message
cannot write task stub because {} is not a generated task stub What it means
mise only overwrites an existing file at a task stub path if its content matches generated stub output (current or legacy format). This error means the file at the stub path has unrecognized content, so mise assumes it is a hand-written file and refuses to clobber it.
Solutions
- Delete the file at the stub path (after saving any manual changes elsewhere) and rerun generation
- Revert manual edits so the content matches the previously generated stub output
- Stop generating stubs for that task and keep the hand-written file as the task entry point
Example fix
// before: hand-edited stub #!/bin/sh exec mise x -- build "$@" # tweaked // after mv .mise/tasks/build ~/backup/ && mise generate task-stubs
Defensive patterns
Strategy: validation
Validate before calling
const existing = fs.readFileSync(stubPath, 'utf8');
if (existing !== generatedOutput && existing !== legacyOutput) {
throw new Error(`${stubPath} is not a generated stub; back it up and remove before regenerating`);
} Try / catch
try {
execSync('mise generate task-stubs');
} catch (e) {
if (String(e).includes('is not a generated task stub')) {
console.error('File was hand-modified or foreign; preserve it, remove, regenerate');
}
} Prevention
- Never edit generated stubs directly; change the task source instead
- Regenerate stubs after mise upgrades if the template changed
- Mark stub files as generated (CODEOWNERS/CI checks) to catch drift
- Keep a backup before force-replacing foreign files at stub paths
When it happens
Trigger: Running `mise generate task-stubs` after a generated stub was manually edited, or where a user's own script exists at the stub path, or where stub output format changed without matching either known template.
Common situations: Hand edits to committed stubs that then drift from the generator; upgrading mise after stub template changes; users placing real task scripts at paths the generator wants to own.
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 create nested task stubs because
- cannot write Windows launcher because
- cannot create nested task stubs because
- cannot create task stub directory because
- cannot write native task stub launchers: mise-shim.exe was…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/e6086c7609ae02e1.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/generate/task_stubs.rs:541
Err(err) => return Err(err.into()),
}
}
for stub in stubs {
match fs::symlink_metadata(&stub.path) {
Ok(metadata) if metadata.file_type().is_dir() => {
validate_generated_stub_directory(&stub.path, &stub.output, stub.task, launchers)?;
migrations.insert(StubMigration::Directory(stub.path.clone()));
}
Ok(metadata) if metadata.file_type().is_symlink() => bail!(
"cannot write task stub because {} is a symbolic link",
display_path(&stub.path)
),
Ok(metadata) if metadata.file_type().is_file() => {
let existing = file::read_to_string(&stub.path)?;
let legacy_leaf = stub.legacy_path == stub.path && existing == stub.legacy_output;
if existing != stub.output && !legacy_leaf {
bail!(
"cannot write task stub because {} is not a generated task stub",
display_path(&stub.path)
);
}
}
Ok(_) => bail!(
"cannot write task stub because {} is not a regular file",
display_path(&stub.path)
),
Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}
Err(err) => return Err(err.into()),
}
validate_launcher_path(stub, launchers)?;
for parent in stub.path.ancestors().skip(1) {
match fs::symlink_metadata(parent) {
Ok(metadata)
if metadata.file_type().is_dir()
|| migrations.contains(&StubMigration::File(parent.to_path_buf())) => {}View on GitHub (pinned to 533346cc37)