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
- Check that the shell variable or argument actually contains the checkpoint ID: `echo "${CHK:?empty}"`.
- List valid checkpoints with `mise dot log` and copy a full (or long) UUID prefix.
- Quote arguments so whitespace doesn't split or empty them: `mise dot restore "$1"`.
- 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
- Guard shell variables: `${CHK:?checkpoint id required}`
- Quote CLI arguments so they can't collapse to empty
- Verify variables hold values before passing them as specs
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
- a glob is required
- no history checkpoint matches {spec:?}
- {spec:?} matches more than one checkpoint; use a longer pref
- --changed does not accept target arguments
- at least one target or --changed is required
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/c0a54b10b93a3fe7.
Report an issue: GitHub.