gitbutlerapp/gitbutler · error

Expected branch identifier, got {}. Please use a branch name

Error message

Expected branch identifier, got {}. Please use a branch name or branch CLI ID.

What it means

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.

Source

Thrown at crates/but/src/command/legacy/push.rs:1143

            })
            .collect();

        if !branch_names.is_empty() {
            return Err(anyhow::anyhow!(
                "Ambiguous branch identifier '{}'. Did you mean one of:\n{}",
                branch_id,
                format_branch_suggestions(&branch_names)
            ));
        } else {
            return Err(anyhow::anyhow!(
                "Identifier '{branch_id}' matches multiple non-branch items. Please use a branch name or branch CLI ID."
            ));
        }
    }

    match &cli_ids[0] {
        CliId::Branch(branch) => Ok(branch.name.clone()),
        _ => Err(anyhow::anyhow!(
            "Expected branch identifier, got {}. Please use a branch name or branch CLI ID.",
            cli_ids[0].kind_for_humans()
        )),
    }
}

fn get_available_branch_names(ctx: &Context) -> anyhow::Result<Vec<String>> {
    let stacks = crate::legacy::workspace::applied_stacks(ctx)?;
    let mut branch_names = Vec::new();

    for stack in stacks {
        for branch in &stack.branches {
            branch_names.push(branch.name.clone());
        }
    }

    branch_names.sort();
    branch_names.dedup();

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Use the branch's name or its branch CLI id (both shown by `but status`)
  2. If you meant a specific commit, use the command that accepts commits (reword, resolve) instead of push
  3. Double-check the id kind before passing it

Example fix

# before
but push 4a2f9
# error: Expected branch identifier, got commit...

# after
but push feature-x   # branch name or branch CLI id
Defensive patterns

Strategy: validation

Validate before calling

# Verify the argument is a branch before pushing
but status | grep -F "$target" || echo "'$target' is not a workspace branch" >&2

Type guard

fn as_branch_name(id: &CliId) -> Option<&str> {
    match id {
        CliId::Branch(b) => Some(b.name.as_str()),
        _ => None,
    }
}

Try / catch

let err = String::from_utf8_lossy(&out.stderr).to_string();
if err.contains("Expected branch identifier") {
    // re-prompt for a branch name or branch CLI id; the message names the actual kind
}

Prevention

When it happens

Trigger: Passing a commit short-id or review id to `but push <id>` where it resolves uniquely to a non-branch item.

Common situations: Copying a change/commit id from logs or `but oplog` and using it where a branch is expected; workspace ids reassigned after history changes.

Related errors


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