{"record":{"id":"1cb7e77f06af8648","repo":"gitbutlerapp/gitbutler","slug":"expected-branch-identifier-got-please-use-a-b","errorCode":null,"errorMessage":"Expected branch identifier, got {}. Please use a branch name or branch CLI ID.","messagePattern":"Expected branch identifier, got (.+?)\\. Please use a branch name or branch CLI ID\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/push.rs","lineNumber":1143,"sourceCode":"            })\n            .collect();\n\n        if !branch_names.is_empty() {\n            return Err(anyhow::anyhow!(\n                \"Ambiguous branch identifier '{}'. Did you mean one of:\\n{}\",\n                branch_id,\n                format_branch_suggestions(&branch_names)\n            ));\n        } else {\n            return Err(anyhow::anyhow!(\n                \"Identifier '{branch_id}' matches multiple non-branch items. Please use a branch name or branch CLI ID.\"\n            ));\n        }\n    }\n\n    match &cli_ids[0] {\n        CliId::Branch(branch) => Ok(branch.name.clone()),\n        _ => Err(anyhow::anyhow!(\n            \"Expected branch identifier, got {}. Please use a branch name or branch CLI ID.\",\n            cli_ids[0].kind_for_humans()\n        )),\n    }\n}\n\nfn get_available_branch_names(ctx: &Context) -> anyhow::Result<Vec<String>> {\n    let stacks = crate::legacy::workspace::applied_stacks(ctx)?;\n    let mut branch_names = Vec::new();\n\n    for stack in stacks {\n        for branch in &stack.branches {\n            branch_names.push(branch.name.clone());\n        }\n    }\n\n    branch_names.sort();\n    branch_names.dedup();","sourceCodeStart":1125,"sourceCodeEnd":1161,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/push.rs#L1125-L1161","documentation":"Exactly one CLI id matched the argument, but it is not a branch — `kind_for_humans()` names what it actually is (for example a commit). Commands that require a branch reject it, since a single non-branch match cannot be coerced into one.","triggerScenarios":"Passing a commit short-id or review id to `but push <id>` where it resolves uniquely to a non-branch item.","commonSituations":"Copying a change/commit id from logs or `but oplog` and using it where a branch is expected; workspace ids reassigned after history changes.","solutions":["Use the branch's name or its branch CLI id (both shown by `but status`)","If you meant a specific commit, use the command that accepts commits (reword, resolve) instead of push","Double-check the id kind before passing it"],"exampleFix":"# before\nbut push 4a2f9\n# error: Expected branch identifier, got commit...\n\n# after\nbut push feature-x   # branch name or branch CLI id","handlingStrategy":"validation","validationCode":"# Verify the argument is a branch before pushing\nbut status | grep -F \"$target\" || echo \"'$target' is not a workspace branch\" >&2","typeGuard":"fn as_branch_name(id: &CliId) -> Option<&str> {\n    match id {\n        CliId::Branch(b) => Some(b.name.as_str()),\n        _ => None,\n    }\n}","tryCatchPattern":"let err = String::from_utf8_lossy(&out.stderr).to_string();\nif err.contains(\"Expected branch identifier\") {\n    // re-prompt for a branch name or branch CLI id; the message names the actual kind\n}","preventionTips":["Pass branch names or branch CLI ids to branch-targeting commands","Use commit-targeting commands (reword, resolve) for commit ids","Read the 'got <kind>' part of the message — it tells you what the id actually matched"],"tags":["push","branch-resolution","cli-id","type-mismatch"],"backgroundTag":"identifier-type-mismatch","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}