jdx/mise · error

cannot write Windows launcher because {} is not a regular fi

Error message

cannot write Windows launcher because {} is not a regular file

What it means

The Windows launcher path bin/<task>.cmd exists but is not a regular file (a directory, a symlink, or another special object). mise cannot write the launcher onto it, so validation fails before any stub is written.

Source

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

///
/// The stub path is the user's choice, so `bin/<task>.cmd` is a name a project may already be
/// using for a script of its own — and unlike the stub itself, nothing about the name says mise
/// owns it. Checked during validation rather than at the write, so a launcher that is not ours
/// stops the whole run instead of leaving a half-generated `bin/`.
fn validate_launcher_path(stub: &TaskStub<'_>) -> Result<()> {
    let Some(launcher) = super::windows_launcher_path(&stub.path) else {
        return Ok(());
    };
    match fs::symlink_metadata(&launcher) {
        Ok(metadata) if metadata.file_type().is_file() => {
            if !super::is_generated_launcher(&file::read_to_string(&launcher)?) {
                bail!(
                    "cannot write Windows launcher because {} is not a generated launcher",
                    display_path(&launcher)
                );
            }
        }
        Ok(_) => bail!(
            "cannot write Windows launcher because {} is not a regular file",
            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) -> 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

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Remove the offending object: `rm -rf bin/<task>.cmd`
  2. Rename the task so the sibling launcher path differs
  3. Generate into another --dir that is clean

Example fix

# before
$ ls -ld bin/build.cmd   # it is a directory
$ mise generate task-stubs
# error: bin/build.cmd is not a regular file

# after
$ rm -rf bin/build.cmd
$ mise generate task-stubs
Defensive patterns

Strategy: type-guard

Validate before calling

#!/bin/bash
for f in bin/*.cmd; do
  [ -e "$f" ] && [ ! -f "$f" ] && { echo "$f is not a regular file" >&2; exit 1; }
done
mise generate task-stubs

Type guard

launcher_path_free() {
  # 0 when <stub>.cmd is absent or a regular file
  [ ! -e "$1.cmd" ] || { [ -f "$1.cmd" ] && [ ! -L "$1.cmd" ]; }
}

Prevention

When it happens

Trigger: `mise generate task-stubs` when a directory or other non-file object is named bin/<task>.cmd — usually an accidental `mkdir bin/task.cmd` or a symlinked bin layout.

Common situations: Tools that create `<name>.cmd/` directories; misnamed folders; symlink farms under bin/.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/ee9275c096880e06. Report an issue: GitHub.