jdx/mise · error

invalid pinned revision

Error message

invalid pinned revision

What it means

install_at requires the revision to be a full git object hash: exactly 40 hex chars (SHA-1) or 64 hex chars (SHA-256). Anything else — branch names, short SHAs, tags — is rejected so the install is always pinned to an immutable commit.

Source

Thrown at src/system/remote_repository.rs:191

        update,
        yes,
        dry_run,
        &global_directory(),
    )
}

fn install_at(
    bundle: &Path,
    origin: &str,
    revision: &str,
    update: bool,
    yes: bool,
    dry_run: bool,
    destination: &Path,
) -> Result<PathBuf> {
    validate_origin(origin)?;
    if !matches!(revision.len(), 40 | 64) || !revision.bytes().all(|b| b.is_ascii_hexdigit()) {
        bail!("invalid pinned revision");
    }
    if destination.is_symlink() {
        bail!("global configuration directory must not be a symlink");
    }
    let parent = destination
        .parent()
        .ok_or_else(|| eyre::eyre!("missing parent directory"))?;
    if !dry_run {
        std::fs::create_dir_all(parent)?;
    }
    let _lock = crate::lock_file::LockFile::new(destination).lock()?;
    // the checkout is renamed into place, so it is staged next to the
    // destination; a dry run never renames and leaves the parent alone
    let temporary = if dry_run {
        tempfile::tempdir()?
    } else {
        tempfile::tempdir_in(parent)?
    };

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Resolve the ref to a full hash first: git rev-parse main
  2. Use the complete 40- or 64-character commit hash
  3. Do not pass tags or branch names to install_at

Example fix

// before
install_at(origin, "abc1234", ...);
// after
let rev = git_rev_parse("abc1234"); // full 40-hex hash
install_at(origin, &rev, ...);
Defensive patterns

Strategy: validation

Validate before calling

fn is_pinned_revision(rev: &str) -> bool {
    matches!(rev.len(), 40 | 64) && rev.bytes().all(|b| b.is_ascii_hexdigit())
}

Type guard

fn full_sha(input: &str) -> Option<String> {
    let ok = matches!(input.len(), 40 | 64)
        && input.bytes().all(|b| b.is_ascii_hexdigit());
    if ok { Some(input.to_lowercase()) } else { None }
}

Prevention

When it happens

Trigger: Calling install_at (or install / install_source / preview_source) with a revision like "main", "v1.2.3", or a 7-char short SHA.

Common situations: Passing a branch or tag name where a pinned commit is expected, or a truncated SHA copied from a log viewer.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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