gitbutlerapp/gitbutler · error
" " is ambiguous. Please provide more characters to…
Error message
"{target}" is ambiguous. Please provide more characters to uniquely identify it. What it means
Thrown by parse_commit_or_branch when the IdMap returns more than one match for the target — the identifier is a valid prefix but is ambiguous. The user must supply more characters (or a longer name) to make it unique.
Solutions
- Provide more characters of the commit hash.
- Use the full branch name.
- Run `but status` to see which identifiers collide.
Example fix
// before but resolve ab // after but resolve ab34f9c
Defensive patterns
Strategy: validation
Validate before calling
const matches = idMap.parse(target);
if (matches.length > 1) throw new Error(`"${target}" is ambiguous; candidates: ${matches.map(m => m.display).join(', ')}`); Try / catch
try { await butResolve(prefix) } catch (e) { if (String(e).includes('ambiguous')) { listCandidates(prefix); } } Prevention
- Use at least 7-8 characters of a commit hash.
- Prefer full branch names over prefixes.
- Disambiguate similarly named branches before scripting.
When it happens
Trigger: `but resolve <prefix> ...` where the short commit-hash prefix or partial branch name matches 2+ CliIds in the workspace.
Common situations: Short SHAs that share a prefix; similarly named branches like feature/x and feature/x-2.
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
- " " does not refer to a commit or a branch
- " " is neither a commit nor a branch. Try running 'but…
- Aborting due to empty branch name
- Ambiguous branch ' ', matches multiple items
- Ambiguous branch identifier
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/bd0070e66e550636.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/command/legacy/resolve.rs:714
}
enum CommitOrBranch {
Commit(gix::ObjectId),
Branch(String),
}
/// Resolve a user-provided identifier to a commit or a branch.
fn parse_commit_or_branch(ctx: &mut Context, target: &str) -> Result<CommitOrBranch> {
let id_map = IdMap::legacy_new_from_context(ctx)?;
let matches = id_map.parse_using_context(target, ctx)?;
match matches.as_slice() {
[] => bail!(
"\"{target}\" is neither a commit nor a branch. Try running 'but status' to see what is available."
),
[CliId::Commit { commit, .. }] => Ok(CommitOrBranch::Commit(commit.commit_id)),
[CliId::Branch(branch)] => Ok(CommitOrBranch::Branch(branch.name.clone())),
[_] => bail!("\"{target}\" does not refer to a commit or a branch"),
_ => bail!(
"\"{target}\" is ambiguous. Please provide more characters to uniquely identify it."
),
}
}
/// List the conflicts of a conflicted commit without entering resolution mode.
fn list_conflicts(ctx: &mut Context, out: &mut OutputChannel, commit: Option<&str>) -> Result<()> {
let t = theme::get();
let Some(target) = target_conflicted_commit(ctx, commit)? else {
if let Some(human_out) = out.for_human() {
writeln!(
human_out,
"{}",
t.success.paint("No conflicted commits found.")
)?;
}
if let Some(json_out) = out.for_json() {
json_out.write_value(serde_json::json!({ "commit_id": null, "files": [] }))?;View on GitHub (pinned to 58e5313667)