jdx/mise · error

`{dp}` is not executable. {}

Error message

`{dp}` is not executable. {}

What it means

A file-based task (task.file exists) must be executable for `mise run` to launch it. On Windows, `chmod` is meaningless — mise decides executability by shebang or by file extension (windows_executable_extensions setting) — so the interactive 'make executable?' fix is skipped (it could not change the answer) and mise directly bails with the platform-correct remedy.

Source

Thrown at src/cli/run.rs:1383

        if self.task_cache.enabled() && task.cache.as_ref().is_some_and(|cache| cache.enabled) {
            Settings::get().ensure_experimental("task artifact caching")?;
        }
        if task.rust_cache.as_ref().is_some_and(|cache| cache.enabled) {
            Settings::get().ensure_experimental("Rust action caching")?;
        }
        if !task.pass_through_env.is_empty() {
            Settings::get().ensure_experimental("task environment pass-through")?;
        }
        if let Some(path) = &task.file
            && path.exists()
            && !file::is_executable(path)
        {
            let dp = crate::file::display_path(path);
            // Only offer the fix where accepting it can change the answer. `make_executable` is a
            // no-op on Windows, so the prompt would take a "yes" and then fail anyway; the same
            // reasoning already keeps `make_task_executable` from running there.
            if cfg!(windows) {
                bail!(
                    "`{dp}` is not executable. {}",
                    file::make_executable_hint(path)
                )
            }
            let msg = format!("Script `{dp}` is not executable. Make it executable?");
            if ui::confirm(msg)? {
                file::make_executable(path)?;
            } else {
                bail!(
                    "`{dp}` is not executable. {}",
                    file::make_executable_hint(path)
                )
            }
        }
        Ok(())
    }

    fn timings(&self) -> bool {

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Add a shebang line as the first line of the script (e.g. `#!/bin/sh` or `#!/usr/bin/env python`)
  2. Rename the script with an accepted extension (see the list in the error text / the windows_executable_extensions setting), and update the task's file path
  3. Or convert the task to a `run = "..."` command in mise.toml/tasks.toml so no script file is needed

Example fix

# before: tasks/hello.txt with `echo hi`
mise run hello
# after: rename to tasks/hello.ps1 (extension in windows_executable_extensions), or add `#!/bin/sh` as line 1
mise run hello
Defensive patterns

Strategy: validation

Validate before calling

# bash (run on the authoring machine, cross-platform intent)
head -c2 "$script" | grep -q '#!' || case "$script" in *.exe|*.bat|*.cmd|*.ps1) ;; *) echo "$script needs a shebang or a Windows-executable extension" >&2; exit 1;; esac
mise run "$task"

Type guard

is_windows_executable_script() {
  head -c2 "$1" | grep -q '#!' && return 0
  case "$1" in *.exe|*.bat|*.cmd|*.ps1) return 0;; *) return 1;; esac
}

Prevention

When it happens

Trigger: `mise run <task>` on Windows where the task's script file has no shebang and no extension listed in windows_executable_extensions (default: .exe, .bat, .cmd, .ps1, …).

Common situations: Checking a Unix-authored tasks/ script into a Windows checkout (no extension, no or unrecognized shebang); generated task files missing a shebang; users who changed windows_executable_extensions and renamed files inconsistently.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/652b2cfdcf414f86. Report an issue: GitHub.