{"record":{"id":"52177ca3914d8a76","repo":"gitbutlerapp/gitbutler","slug":"ambiguous-branch-branch-id-matches-multiple-i","errorCode":null,"errorMessage":"Ambiguous branch '{branch_id}', matches multiple items","messagePattern":"Ambiguous branch '(.+?)', matches multiple items","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/land/mod.rs","lineNumber":48,"sourceCode":"        let mut guard = ctx.exclusive_worktree_access();\n\n        {\n            let (_repo, ws, _db) = ctx.workspace_and_db_with_perm(guard.read_permission())?;\n            if !ws.kind.has_managed_ref() {\n                bail!(\n                    \"`but land` requires an active GitButler workspace (`gitbutler/workspace`). \\\n                     Switch into the workspace and try again.\"\n                );\n            }\n        }\n\n        let id_map = IdMap::new_from_context(ctx, guard.read_permission())?;\n        let resolved_ids = id_map.parse_using_context(branch_id, ctx)?;\n        if resolved_ids.is_empty() {\n            bail!(\"Could not find branch: {branch_id}\");\n        }\n        if resolved_ids.len() > 1 {\n            bail!(\"Ambiguous branch '{branch_id}', matches multiple items\");\n        }\n\n        let branch_name = match &resolved_ids[0] {\n            CliId::Branch(branch) => branch.name.clone(),\n            other => bail!(\"Expected a branch ID, got {}\", other.kind_for_humans()),\n        };\n\n        let base_branch =\n            but_api::legacy::virtual_branches::get_base_branch_data(ctx, guard.write_permission())?\n                .ok_or_else(|| anyhow::anyhow!(\"No base branch configured\"))?;\n        (branch_name, base_branch)\n    };\n\n    // Display strings for the prompt and the final report. The API recomputes the target/remote\n    // configuration internally; the CLI only needs these names to describe what's about to happen.\n    let target_branch_name = base_branch.short_name.clone();\n    let push_remote_name = if base_branch.push_remote_name.is_empty() {\n        base_branch.remote_name.clone()","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/land/mod.rs#L30-L66","documentation":"Short CLI IDs are prefixes into the workspace IdMap. When one prefix matches more than one entity, `but land` refuses to guess and bails with 'Ambiguous branch' (land/mod.rs:47-49); you must disambiguate before the command can proceed.","triggerScenarios":"`but land <prefix>` where the prefix is also a prefix of two or more IDs — e.g. single-character prefixes like `1` or `b` in a workspace with many branches, commits, and uncommitted files.","commonSituations":"Copy-truncated IDs; workspaces that grew so previously-unique short prefixes now collide; scripts reusing a hardcoded prefix that was unique when written.","solutions":["Add more characters to the ID until it is unique (verify in `but status`).","Use the full branch name instead of the short ID.","In scripts, resolve the full ID once and store that, rather than reusing brittle prefixes."],"exampleFix":"# before\nbut land 1          # '1' matches several entities -> Ambiguous branch\n\n# after\nbut land 1a3 --yes  # longer, unique prefix\nbut land my-branch --yes","handlingStrategy":"validation","validationCode":"# Cheap uniqueness check before running: count matches of the prefix in status output\ncount=$(but status | grep -cF '<id>')\n[ \"$count\" -eq 1 ] || { echo 'ambiguous id'; exit 2; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lengthen prefixes until unique; prefer full branch names in automation.","Refresh IDs after history-rewriting operations (rebase, squash, amend)."],"tags":["cli","id-resolution","ambiguous","land","gitbutler"],"backgroundTag":"ambiguous-identifier","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}