{"record":{"id":"af1ad8b934460549","repo":"gitbutlerapp/gitbutler","slug":"expected-a-local-branch-but-is-a-remote-tracking-branch","errorCode":null,"errorMessage":"Expected a local branch, but '{}' is a remote-tracking branch","messagePattern":"Expected a local branch, but '(.+?)' is a remote-tracking branch","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/branch/update.rs","lineNumber":144,"sourceCode":"                        commit_id: commit_id.into(),\n                    }\n                }\n            })\n            .collect(),\n    }\n}\n\nfn resolve_local_branch(ctx: &but_ctx::Context, branch: &str) -> anyhow::Result<FullName> {\n    let candidate = normalize_local_branch_ref(branch)?;\n    let repo = ctx.repo.get()?;\n    let Some(reference) = repo.try_find_reference(candidate.as_ref())? else {\n        bail!(\"Local branch '{}' not found\", candidate.shorten());\n    };\n    let reference = reference.detach();\n    match reference.name.category() {\n        Some(Category::LocalBranch) => Ok(reference.name),\n        Some(Category::RemoteBranch) => {\n            bail!(\n                \"Expected a local branch, but '{}' is a remote-tracking branch\",\n                reference.name.shorten()\n            )\n        }\n        _ => bail!(\n            \"Expected a local branch, but '{}' is not under refs/heads/\",\n            reference.name.shorten()\n        ),\n    }\n}\n\nfn normalize_local_branch_ref(branch: &str) -> anyhow::Result<FullName> {\n    let full = if branch.starts_with(\"refs/heads/\") {\n        branch.to_owned()\n    } else if branch.starts_with(\"refs/\") {\n        bail!(\"Only local branches under refs/heads/ are supported\");\n    } else {\n        format!(\"refs/heads/{branch}\")","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but/src/command/branch/update.rs#L126-L162","documentation":"resolve_local_branch found a reference with the given name but of category RemoteBranch. `but branch update` only operates on local branches, so it rejects remote-tracking refs like refs/remotes/origin/main.","triggerScenarios":"Passing a remote-tracking ref (e.g. `origin/main` or `refs/remotes/origin/main`) to `but branch update`, causing normalize_local_branch_ref's refs/ handling or the lookup to land on a RemoteBranch-category reference.","commonSituations":"Users habitually prefixing branches with `origin/` as in git workflows; scripts parameterized with remote refs; IDE-provided refs copied from the remote branch list.","solutions":["Use the local branch name without the remote prefix: `main` instead of `origin/main`.","If only the remote branch exists, check out a local tracking branch first.","Update a local branch that tracks the remote instead of the remote ref itself."],"exampleFix":"// before\nbut branch update origin/main --to abc123\n// after\nbut branch update main --to abc123","handlingStrategy":"validation","validationCode":"if (name.startsWith('origin/') || name.startsWith('refs/remotes/')) {\n  name = name.replace(/^(refs\\/remotes\\/)?origin\\//, '');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Strip remote prefixes before passing branch names to but commands.","Treat `but branch update` as local-branch-only; sync remotes with push/pull instead.","When scripting from IDE data, sanitize refs to bare local names."],"tags":["git","branch","remote-tracking","cli"],"backgroundTag":"invalid-argument-value","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}