jdx/mise · error
{spec:?} matches more than one checkpoint; use a longer pref
Error message
{spec:?} matches more than one checkpoint; use a longer prefix What it means
When resolving a checkpoint reference by UUID prefix, more than one stored entry may share that prefix. Because the tool cannot know which one is intended, it refuses and asks for a longer prefix that narrows to exactly one match. This is standard short-hash ambiguity handling, mirroring git's behavior.
Source
Thrown at src/system/history/store.rs:927
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()
}
pub(crate) fn write_json<T: Serialize>(path: &Path, value: &T) -> Result<()> {
let mut text = serde_json::to_string_pretty(value)?;
text.push('\n');
if let Some(parent) = path.parent() {
file::create_dir_all(parent)?;
}
file::write_atomic(path, text).wrap_err_with(|| format!("writing {}", display_path(path)))?;View on GitHub (pinned to afd2eddd3a)
Solutions
- Repeat the command with more characters of the UUID until it's unique.
- Use the full UUID from `mise dot log` to be unambiguous.
- In scripts, resolve the full ID once and reuse it instead of a short prefix.
- If two checkpoints really are duplicates of the same state, prune one from history.
Example fix
// before
let id = resolve_checkpoint("a")?; // ambiguous
// after
let full = list_checkpoints()?.iter().find(|c| c.checkpoint.uuid.starts_with("a")).unwrap().checkpoint.uuid.clone();
let id = resolve_checkpoint(&full)?; Defensive patterns
Strategy: validation
Validate before calling
let hits: Vec<_> = list_checkpoints()?.into_iter().filter(|c| c.checkpoint.uuid.starts_with(prefix)).collect();
if hits.len() > 1 {
eprintln!("prefix {prefix:?} is ambiguous; use a longer prefix or the full uuid");
} Try / catch
match resolve_checkpoint(prefix) {
Ok(id) => use(id),
Err(e) if e.to_string().contains("matches more than one checkpoint") => {
eprintln!("extend the prefix; candidates listed in `mise dot log`");
}
Err(e) => return Err(e),
} Prevention
- Prefer full UUIDs over short prefixes in scripts
- Use at least 6-8 characters of prefix as history grows
- Resolve the full id once and store it, rather than re-resolving prefixes
When it happens
Trigger: Calling the checkpoint-resolution API with a short prefix (often 1-2 characters) that matches two or more checkpoint UUIDs in the store.
Common situations: Using a very short prefix in a store with many checkpoints; scripting with a fixed-length prefix assumption that breaks as history grows.
Related errors
- invalid checkpoint reference {spec:?}
- no history checkpoint matches {spec:?}
- --changed does not accept target arguments
- at least one target or --changed is required
- --source can only be used with one target
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/3ce8702dbf41316d.
Report an issue: GitHub.