jdx/mise · error

invalid checkpoint reference {spec:?}

Error message

invalid checkpoint reference {spec:?}

What it means

Checkpoint references in dotfile history can be a UUID prefix or an ID. After resolving any non-empty spec through the entry list, the code checks the resulting prefix; if it is empty, the spec cannot name any checkpoint and the error reports the original spec verbatim. This guards against empty or effectively-empty references reaching the prefix-matching stage.

Source

Thrown at src/system/history/store.rs:918

                )
            });
    }
    let prefix = if let Some(prefix) = spec.strip_prefix("commit:") {
        prefix
    } else if !spec.is_empty() && spec.bytes().all(|byte| byte.is_ascii_digit()) {
        let id = spec.parse::<u64>().map_err(|_| {
            eyre!("invalid checkpoint ID {spec:?}; use commit:<sha> for a numeric commit hash")
        })?;
        return entries
            .iter()
            .find(|entry| entry.id == id)
            .map(|entry| entry.id)
            .ok_or_else(|| eyre!("no history checkpoint matches {spec:?}"));
    } else {
        spec
    };
    if prefix.is_empty() {
        bail!("invalid checkpoint reference {spec:?}");
    }
    let matches: Vec<&Entry> = entries
        .iter()
        .filter(|entry| entry.checkpoint.uuid.starts_with(prefix))
        .collect();
    match matches.as_slice() {
        [one] => Ok(one.id),
        [] => bail!("no history checkpoint matches {spec:?}"),
        _ => bail!("{spec:?} matches more than one checkpoint; use a longer prefix"),
    }
}

pub(crate) fn now_rfc3339() -> String {
    chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true)
}

pub(crate) fn new_uuid() -> String {
    uuid::Uuid::now_v7().to_string()

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Check that the shell variable or argument actually contains the checkpoint ID: `echo "${CHK:?empty}"`.
  2. List valid checkpoints with `mise dot log` and copy a full (or long) UUID prefix.
  3. Quote arguments so whitespace doesn't split or empty them: `mise dot restore "$1"`.
  4. Pass the full UUID instead of a prefix to eliminate ambiguity.

Example fix

// before
let spec = env::var("CHK").unwrap_or_default(); // may be empty
// after
let spec = env::var("CHK").expect("CHK must hold a checkpoint id");
assert!(!spec.is_empty(), "invalid checkpoint reference {spec:?}");
Defensive patterns

Strategy: validation

Validate before calling

let spec = std::env::var("CHK")?;
if spec.trim().is_empty() {
    eprintln!("CHK is empty; provide a checkpoint id from `mise dot log`");
}

Type guard

fn non_empty(s: &str) -> Option<&str> {
    let t = s.trim(); if t.is_empty() { None } else { Some(t) }
}

Try / catch

match resolve_checkpoint(spec) {
    Ok(id) => use(id),
    Err(e) if e.to_string().contains("invalid checkpoint reference") => {
        eprintln!("empty or malformed reference; run `mise dot log` for valid ids");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing an empty string or a spec that resolves to an empty prefix (e.g. `""`, or a spec form that strips to nothing) to the checkpoint-lookup API (`mise dot` restore/checkout with a blank PATH-ish argument).

Common situations: A shell variable holding the checkpoint ID is unset/empty (`mise dot restore "$CHK"` with `CHK=`); copying a reference that trimmed to nothing; a script parameter defaulting to empty.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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