jdx/mise · error

install_mise must be an absolute path or start with ~/

Error message

install_mise must be an absolute path or start with ~/: {path:?}

What it means

`install_mise` must point at an unambiguous location on the remote host: an absolute path starting with '/', or an explicit home-relative path starting with '~/' (which mise expands to a concrete absolute path). Anything else — a bare name, './relative', or a plain '~' — cannot be resolved safely, so this error is thrown.

Solutions

  1. Prefix the path with '/' for an absolute location (e.g. '/usr/local/bin/mise')
  2. Or use '~/...' for a home-relative location (e.g. '~/bin/mise')
  3. Fix typos that leave the value as a bare executable name

Example fix

// before
install_mise = "bin/mise"
// after
install_mise = '~/bin/mise'
Defensive patterns

Strategy: validation

Validate before calling

const ok = typeof p === 'string' && (p.startsWith('/') || p.startsWith('~/'));
if (!ok) throw new Error('install_mise must be absolute or ~/-prefixed');

Type guard

const isInstallablePath = (s: unknown): s is string =>
  typeof s === 'string' && (s.startsWith('/') || s.startsWith('~/'));

Try / catch

try { validate_install_mise_path(p)?; } catch (e) {
  // suggest rewriting to an absolute or ~/-prefixed path
}

Prevention

When it happens

Trigger: install_mise set to a value like 'mise', './bin/mise', 'bin/mise', or just '~'.

Common situations: Copy-pasting a command name instead of an install path; assuming relative paths resolve against HOME; typos dropping the leading '/'.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/system/remote.rs:2219

fn validated_remote_command_output(output: &str) -> Result<String> {
    validated_remote_command(output.strip_suffix('\n').unwrap_or(output))
}

fn validated_absolute_remote_path_output(output: &str, kind: &str) -> Result<String> {
    let path = output.strip_suffix('\n').unwrap_or(output);
    if !path.starts_with('/') || path.contains(['\0', '\n', '\r']) {
        bail!("{kind} returned an unsafe absolute path: {path:?}");
    }
    Ok(path.to_string())
}

fn validate_install_mise_path(path: &str) -> Result<()> {
    validate_value("mise install path", path)?;
    if path.contains(['\n', '\r']) {
        bail!("install_mise must not contain a newline: {path:?}");
    }
    if !path.starts_with('/') && !path.starts_with("~/") {
        bail!("install_mise must be an absolute path or start with ~/: {path:?}");
    }
    if path.split('/').any(|component| component == "..") {
        bail!("install_mise must not contain '..': {path:?}");
    }
    if matches!(
        path.rsplit('/').next(),
        None | Some("") | Some(".") | Some("~")
    ) {
        bail!("install_mise must name an executable file: {path:?}");
    }
    Ok(())
}

fn validate_remote_executable(command: &str) -> Result<()> {
    validate_value("mise command", command)?;
    let is_path = command.contains('/');
    if command.starts_with('-')
        || command.contains(['\n', '\r'])

View on GitHub (pinned to 533346cc37)