jdx/mise · error
invalid checkpoint reference
Error message
invalid checkpoint reference {spec:?} What it means
When resolving a checkpoint reference, mise first tries to expand a spec to a UUID prefix and then match entries. If after expansion the prefix is empty, there is nothing sensible to match against, so mise rejects the spec as invalid rather than matching every entry. This is an input-validation error for checkpoint selectors.
Solutions
- Supply a non-empty checkpoint id or UUID prefix.
- List available checkpoints to copy a valid id.
- Check shell scripts for unset variables feeding the empty spec.
- Quote arguments to avoid the shell stripping them.
Example fix
// before mise dotfiles checkout "$CKPT" # CKPT is unset Error: invalid checkpoint reference "" // after CKPT=$(mise dotfiles history list --latest-id) mise dotfiles checkout "$CKPT"
Defensive patterns
Strategy: validation
Validate before calling
if spec.trim().is_empty() {
eprintln!("checkpoint reference is empty; run `mise dotfiles history list` for valid ids");
} Type guard
fn is_valid_checkpoint_spec(spec: &str) -> bool {
!spec.trim().is_empty()
} Prevention
- Never pass possibly-unset shell variables unquoted into checkpoint commands.
- Default empty specs to 'latest' or an interactive picker in scripts.
- Validate arguments in wrapper scripts before calling mise.
When it happens
Trigger: Passing an empty or whitespace-only checkpoint spec (after the non-UUID branch), or a spec that fails the expansion logic leaving an empty prefix, e.g. `mise dotfiles checkout ""`.
Common situations: A shell variable holding the checkpoint id is unset/empty (`$LATEST` empty); quoting mistake passes an empty argument; script automation drops the id.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- no history checkpoint matches
- matches more than one checkpoint; use a longer prefix
- a repository preview directory requires a dry run
- `--all` needs `--to
- appeared after was protected; nothing more was changed
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/c0a54b10b93a3fe7.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/history/store.rs:1010
)
});
}
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 533346cc37)