jdx/mise · error

MISE_BIN should have a parent directory

Error message

MISE_BIN should have a parent directory

What it means

On Windows self-update, mise writes `mise-shim.exe` next to the running binary using `env::MISE_BIN.parent()`. If `MISE_BIN` is a bare filename with no parent directory component, `.parent()` returns `None` and this `.expect()` panics. It guards the assumption that `MISE_BIN` always holds a full path to the mise executable.

Source

Thrown at src/cli/self_update.rs:660

        fs::write(&zip_path, archive)?;

        // Verify the archive signature using the same key as the main update
        Self::verify_zip_signature(&zip_path)?;

        let file = fs::File::open(&zip_path)?;
        let mut archive = zip::ZipArchive::new(file)?;

        let mut shim_entry = match archive.by_name("mise/bin/mise-shim.exe") {
            Ok(entry) => entry,
            Err(_) => {
                warn!("mise-shim.exe not found in release archive, skipping");
                return Ok(());
            }
        };

        let dest = env::MISE_BIN
            .parent()
            .expect("MISE_BIN should have a parent directory")
            .join("mise-shim.exe");

        // Write to a temp file first, then rename for atomic replacement
        let mut buf = Vec::new();
        shim_entry.read_to_end(&mut buf)?;
        let temp_shim = temp_dir.path().join("mise-shim.exe");
        fs::write(&temp_shim, &buf)?;
        if fs::rename(&temp_shim, &dest).is_err() {
            // Fallback for cross-filesystem moves
            fs::copy(&temp_shim, &dest)?;
        }

        debug!("Updated mise-shim.exe at {}", dest.display());
        Ok(())
    }

    #[cfg(windows)]
    fn verify_zip_signature(path: &std::path::Path) -> Result<()> {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Unset the custom `MISE_BIN` override (or set it to the full path, e.g. `MISE_BIN=C:\\Users\\you\\.local\\bin\\mise.exe`) and retry `mise self-update`
  2. Verify with `echo $MISE_BIN` that it contains a directory separator
  3. Locate the real binary with `which mise` (or `Get-Command mise`) and use that absolute path
  4. Update mise by your package manager instead of `mise self-update` to avoid the shim rewrite entirely

Example fix

// before (shell)
export MISE_BIN=mise
// after
export MISE_BIN="$(which mise)"
Defensive patterns

Strategy: validation

Validate before calling

# Before running `mise self-update` on Windows:
if [ -n "$MISE_BIN" ] && [[ "$MISE_BIN" != */* ]]; then
  export MISE_BIN="$(command -v mise)"
fi
mise self-update

Type guard

# PowerShell
if ($env:MISE_BIN -and -not $env:MISE_BIN.Contains([IO.Path]::DirectorySeparatorChar)) {
  $env:MISE_BIN = (Get-Command mise).Source
}

Prevention

When it happens

Trigger: `MISE_BIN` env var set to a bare name like `mise` instead of an absolute/relative path with a directory (e.g. `MISE_BIN=mise` rather than `MISE_BIN=C:\\bin\\mise.exe`); running `mise self-update` through a wrapper that overrides `MISE_BIN` incorrectly.

Common situations: Users who manually export `MISE_BIN` in their shell profile with just the executable name; launcher scripts or package managers setting `MISE_BIN` to something found via PATH lookup without a directory component.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/3b4133898afba203. Report an issue: GitHub.