jdx/mise · error

cannot replace task stub directory because

Error message

cannot replace task stub directory because {} does not contain the generated stub for task {}

What it means

When `mise generate task-stub` replaces an entire stub directory, it first verifies the `_default` stub inside matches the expected generated content. If the directory has no readable `_default` file whose content equals the generated default stub, mise refuses to replace the directory and throws this error naming the task. This guards against wiping directories that contain user-owned content.

Solutions

  1. Regenerate stubs into a clean directory instead of replacing the existing one
  2. Restore the unmodified generated `_default` file (recreate via mise) before replacing the directory
  3. Back up and remove the directory manually, then re-run `mise generate task-stub`

Example fix

// before: hand-edited _default diverges from generated content
// stubs\_default edited by hand -> replacement blocked
// after: regenerate from scratch
rm -r stubs
mise generate task-stub --task build --output stubs
Defensive patterns

Strategy: validation

Validate before calling

const def = path.join(stubDir, '_default');
if (!fs.existsSync(def) || fs.lstatSync(def).isSymbolicLink()) {
  throw new Error('stub directory lacks a plain generated _default; regenerate into a clean dir');
}

Type guard

const hasPlainDefault = (dir: string): boolean => {
  try { return fs.lstatSync(path.join(dir, '_default')).isFile(); } catch { return false; }
};

Try / catch

try {
  await exec('mise generate task-stub ...');
} catch (e) {
  if (String(e).includes('does not contain the generated stub')) {
    fs.rmSync(stubDir, { recursive: true });
    await exec('mise generate task-stub ...'); // regenerate fresh
  }
}

Prevention

When it happens

Trigger: Running `mise generate task-stub` targeting a directory that: lacks a `_default` child, has `_default` as a non-file (symlink/dir), or whose `_default` content differs from the freshly generated default stub text (edited or produced by an older mise version).

Common situations: Users hand-edited `_default`; a stub was generated by an older mise with different template text; a symlink farm (e.g. dotfiles manager) replaced `_default` with a symlink.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/a385fac14f773f5a. Report an issue: GitHub.

Appendix: source

Thrown at src/cli/generate/task_stubs.rs:616

            display_path(&launcher)
        ),
        Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}
        Err(err) => return Err(err.into()),
    }
    Ok(())
}

fn validate_generated_stub_directory(
    path: &Path,
    expected: &str,
    task: &Task,
    launchers: &Launchers,
) -> Result<()> {
    let default = path.join("_default");
    match fs::symlink_metadata(&default) {
        Ok(metadata)
            if metadata.file_type().is_file() && file::read_to_string(&default)? == expected => {}
        _ => bail!(
            "cannot replace task stub directory because {} does not contain the generated stub for task {}",
            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)?;

View on GitHub (pinned to 533346cc37)