pbakaus/impeccable · error

ambiguous snapshot slug; use an explicit ./path or remove th

Error message

ambiguous snapshot slug; use an explicit ./path or remove the local name collision

What it means

`latest` refuses to answer when the argument is a short 'ready slug' while a local path of that name also exists on disk, and the newest snapshot's recorded target identity does not match the local target's identity — the slug is ambiguous, so the command prints this message and exits 2 without closing or returning a possibly-wrong snapshot.

Source

Thrown at crates/context/src/critique_storage.rs:573

            else {
                return 2;
            };
            let mut latest =
                read_newest_snapshot_for_identity_slugs(&slugs, target_identity.as_deref(), &cwd, &env);
            if latest.is_none() && !ready_slug {
                // Identity-less snapshots are safe only under the new/current
                // collision-resistant slug. A pre-hash slug suffix alone cannot
                // prove which long target owned the historical snapshot.
                latest = slugs.first().and_then(|slug| read_newest_snapshot_for_identity(slug, None, &cwd, &env));
            }
            let latest = latest.unwrap_or(newest_for_slug);
            if meta_closed(&latest) {
                return 2;
            }
            let recorded_target_identity = snapshot_target_identity(&latest);
            let matching_identity = recorded_target_identity == target_identity;
            if ready_slug && target_path.as_deref().map(exists).unwrap_or(false) && !matching_identity {
                io.err("ambiguous snapshot slug; use an explicit ./path or remove the local name collision\n");
                return 2;
            }
            let concrete_target = !ready_slug || matching_identity;
            if concrete_target && recorded_target_identity.is_some() && !matching_identity {
                return 2;
            }
            let concrete_local_target = concrete_target && target_path.is_some();
            if concrete_local_target {
                let recorded_fp = match latest.meta.get("target_fingerprint") {
                    Some(Value::String(s)) => Some(s.clone()),
                    _ => None,
                };
                // JS strict `!==`: equal only when both are the same string;
                // undefined/null on either side always differ.
                let differ = !matches!((&recorded_fp, &target_fingerprint), (Some(a), Some(b)) if a == b);
                if differ {
                    return match close_snapshot(&latest.path, &cwd, &env) {
                        Err(e) => {

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Disambiguate by passing the explicit local path with `./` prefix: `latest ./mypage`.
  2. Remove or rename the local file that collides with the snapshot slug.
  3. If the local target is the one you mean, recreate/overwrite the snapshot via `write` so its recorded identity matches.
  4. Use the fully resolved path form of the target instead of the short slug.

Example fix

// before
latest mypage
// ambiguous: local ./mypage exists with different identity
// after
latest ./mypage
Defensive patterns

Strategy: validation

Validate before calling

const localName = target.replace(/^\.\//, '');
if (!target.startsWith('./') && fs.existsSync(localName)) {
  target = './' + localName; // disambiguate short slug from local file
}

Prevention

When it happens

Trigger: Calling `critique-storage latest mypage` when both a snapshot for slug `mypage` exists AND a file/directory named `mypage` exists in the cwd, and the snapshot was recorded against a different target identity (e.g. the local `mypage` was recreated or points elsewhere).

Common situations: A target file was deleted and recreated under the same short name, the cwd changed so a same-named local file now shadows the slug, or snapshots exist from an older project sharing the slug.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/ee9236698393cd5d. Report an issue: GitHub.