jdx/mise · error

cannot create nested task stubs because

Error message

cannot create nested task stubs because {} is not a directory

What it means

During nested task stub generation, mise checks every ancestor path of each stub. If a legacy stub path exists but is neither a directory nor a migratable file (e.g. a FIFO, device, or other special file), mise cannot create the required directory and aborts with this error.

Solutions

  1. Inspect the path with `ls -la` and remove or replace the special file with a directory
  2. If it is a stale artifact, delete it and rerun `mise generate task-stubs`
  3. Check for symlinks pointing at unexpected targets and fix them

Example fix

// before
$ ls -la .mise/tasks/build
prw-r--r-- build  # FIFO
// after
$ rm .mise/tasks/build && mise generate task-stubs
Defensive patterns

Strategy: validation

Validate before calling

const st = fs.lstatSync(legacyPath);
if (st.exists && !st.isDirectory() && !st.isFile()) {
  throw new Error(`${legacyPath} is a special file; remove it before generating nested stubs`);
}

Type guard

const isRegularOrDir = (st: fs.Stats) => st.isFile() || st.isDirectory();

Prevention

When it happens

Trigger: Running `mise generate task-stubs` where a path that must become a stub directory (a legacy stub location) exists as a non-regular, non-directory filesystem entry such as a named pipe or socket.

Common situations: Rare filesystem oddities: leftover special files at task paths, symlink targets resolving to special files, or corrupted checkouts on unusual filesystems.

Related errors


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

Appendix: source

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

    stubs: &[TaskStub<'_>],
    launchers: &Launchers,
) -> Result<Vec<StubMigration>> {
    let mut migrations = HashSet::new();
    for stub in stubs.iter().filter(|stub| stub.legacy_path != stub.path) {
        match fs::symlink_metadata(&stub.legacy_path) {
            Ok(metadata) if metadata.file_type().is_file() => {
                let existing = file::read_to_string(&stub.legacy_path)?;
                if existing != stub.output && existing != stub.legacy_output {
                    bail!(
                        "cannot create nested task stubs because {} is not the generated stub for task {}",
                        display_path(&stub.legacy_path),
                        stub.task.display_name
                    );
                }
                migrations.insert(StubMigration::File(stub.legacy_path.clone()));
            }
            Ok(metadata) if metadata.file_type().is_dir() => {}
            Ok(_) => bail!(
                "cannot create nested task stubs because {} is not a directory",
                display_path(&stub.legacy_path)
            ),
            Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}
            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)
            ),

View on GitHub (pinned to 533346cc37)