gitbutlerapp/gitbutler · error · anyhow::Error

Could not find {kind} CLI id '{short_id}' in IdMap

Error message

Could not find {kind} CLI id '{short_id}' in IdMap

What it means

Thrown by `lookup_cli_id_for_short_id` (used by TUI/status commands): the short id string is parsed against the IdMap, matches are kept only if their canonical `to_short_string()` equals the input and they pass a kind predicate (e.g. commit vs branch). Zero surviving matches produces this error — the id is not registered for that kind.

Source

Thrown at crates/but/src/command/legacy/status/mod.rs:1852

            ]),
        )?;
    }
    Ok(())
}

fn lookup_cli_id_for_short_id(
    id_map: &IdMap,
    repo: &gix::Repository,
    short_id: &str,
    predicate: impl Fn(&CliId) -> bool,
    kind: &str,
) -> anyhow::Result<CliId> {
    let mut matches = id_map.parse_using_repo(short_id, repo)?;
    matches.retain(|id| id.to_short_string() == short_id && predicate(id));

    match matches.len() {
        1 => Ok(matches.remove(0)),
        0 => Err(anyhow::anyhow!(
            "Could not find {kind} CLI id '{short_id}' in IdMap"
        )),
        _ => Err(anyhow::anyhow!(
            "CLI id '{short_id}' is ambiguous for {kind} in IdMap"
        )),
    }
}

fn status_letter(status: &TreeStatus) -> char {
    match status {
        TreeStatus::Addition { .. } => 'A',
        TreeStatus::Deletion { .. } => 'D',
        TreeStatus::Modification { .. } => 'M',
        TreeStatus::Rename { .. } => 'R',
    }
}

pub fn status_letter_ui(status: &ui::TreeStatus) -> char {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Rerun `but status` (or the list command for that kind) and copy a fresh short id
  2. Double-check the id kind matches what the command expects (commit id for commit commands, branch id for branch commands)
  3. Use the full-length git sha where the command accepts it — it bypasses short-id ambiguity and staleness
  4. Retype the id carefully; a single wrong character makes the exact-string match fail

Example fix

# before: id from yesterday's output
but <cmd> c7

# after: refresh and use current ids
but status
but <cmd> c4   # id as printed just now
Defensive patterns

Strategy: validation

Validate before calling

let matches = id_map.parse_using_repo(short_id, repo)?;
let hits: Vec<_> = matches
    .into_iter()
    .filter(|id| id.to_short_string() == short_id && kind_predicate(id))
    .collect();
if hits.is_empty() {
    anyhow::bail!("no {kind} id '{short_id}'; refresh with 'but status' and copy a current id");
}

Try / catch

match lookup_cli_id_for_short_id(id_map, repo, short_id, |i| is_commit(i), "commit") {
    Ok(cli_id) => { /* use */ }
    Err(err) if err.to_string().contains("Could not find") => {
        // re-list ids and retry with a fresh one
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Passing a short id copied from stale `but status` output after ids shifted; a typo in the short id; passing a commit id where the command's predicate only accepts another kind, filtering out the real match.

Common situations: Piping ids between invocations across a rebase/amend/ship that renumbered them; reusing ids from a different workspace or project; scripts holding on to ids for too long.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/4de78751220c6efe. Report an issue: GitHub.