{"record":{"id":"a0dbd78366bf2ca0","repo":"gitbutlerapp/gitbutler","slug":"expected-ref-name-to-be-a-remote-tracking-bran","errorCode":null,"errorMessage":"Expected '{ref_name}' to be a remote tracking branch, but was {category:?}","messagePattern":"Expected '(.+?)' to be a remote tracking branch, but was (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/ui/ref_info.rs","lineNumber":67,"sourceCode":"    pub display_name: String,\n    /// The symbolic name of the remote, like `origin`, or `origin/other`.\n    pub remote_name: String,\n}\n#[cfg(feature = \"export-schema\")]\nbut_schemars::register_sdk_type!(RemoteTrackingReference);\n\nimpl RemoteTrackingReference {\n    /// Create a new instance from `ref_name` and `remote_names`, essentially splitting the remote\n    /// name off the short name.\n    pub fn for_ui(\n        ref_name: gix::refs::FullName,\n        remote_names: &gix::remote::Names,\n    ) -> anyhow::Result<Self> {\n        let (category, _short_name) = ref_name.category_and_short_name().with_context(|| {\n            format!(\"Failed to categorize presumed remote reference '{ref_name}'\")\n        })?;\n        if category != Category::RemoteBranch {\n            bail!(\"Expected '{ref_name}' to be a remote tracking branch, but was {category:?}\");\n        }\n        let (longest_remote, short_name) =\n            extract_remote_name_and_short_name(ref_name.as_ref(), remote_names)\n                .ok_or(anyhow::anyhow!(\n                    \"Failed to find remote branch's corresponding remote\"\n                ))\n                .with_context(|| {\n                    format!(\n                        \"Remote reference '{ref_name}' couldn't be matched with any known remote\"\n                    )\n                })?;\n\n        Ok(RemoteTrackingReference {\n            display_name: short_name.to_str_lossy().into_owned(),\n            remote_name: longest_remote,\n            full_name_bytes: ref_name.into_inner(),\n        })\n    }","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/ui/ref_info.rs#L49-L85","documentation":"Thrown by RefInfo::for_ui when the reference it was given categorizes as something other than a remote tracking branch (e.g. a local branch, tag, or note ref). The function exists solely to build UI metadata for remote-tracking refs, so any other category is rejected. The categorization comes from gix's ref_name.category_and_short_name().","triggerScenarios":"Calling for_ui with a fully-qualified ref like refs/heads/main (local branch) or refs/tags/v1 instead of refs/remotes/origin/main; or after a ref rewrite changed the ref's category.","commonSituations":"Passing the workspace's local ref name instead of its upstream counterpart into remote-ref UI helpers; ambiguous or renamed refs after fetch/prune; callers assuming every workspace ref has a remote.","solutions":["Ensure the ref is under refs/remotes/ before calling for_ui; use the tracking ref, not the local branch.","Check ref_name.category_and_short_name() yourself first and pick the right UI path per category.","If the branch has no upstream, create/push a tracking branch or handle the no-remote case in the caller."],"exampleFix":"// before\nRefInfo::for_ui(repo, ref_name, remotes)?; // may be a local branch\n\n// after\nlet (category, _) = ref_name.category_and_short_name()?;\nif category == Category::RemoteBranch {\n    RefInfo::for_ui(repo, ref_name, remotes)?;\n} else {\n    local_ref_info(ref_name)?;\n}","handlingStrategy":"type-guard","validationCode":"fn is_remote_branch(ref_name: &gix::refs::FullNameRef) -> bool {\n    matches!(ref_name.category_and_short_name(), Ok((Category::RemoteBranch, _)))\n}","typeGuard":"// narrowing helper\nfn as_remote_branch(r: &gix::refs::FullNameRef) -> Option<&str> {\n    let (cat, short) = r.category_and_short_name().ok()?;\n    (cat == Category::RemoteBranch).then(|| short.as_bstr().to_str().ok())?.map(str::to_owned)\n}","tryCatchPattern":"match RefInfo::for_ui(...) {\n    Err(e) if e.to_string().contains(\"remote tracking branch\") => local_ref_info(ref_name)?,\n    other => other?,\n}","preventionTips":["Verify the ref category before choosing the UI metadata builder","Pass refs/remotes/* refs to remote-specific helpers, local branches elsewhere","Handle branches without upstreams explicitly instead of forcing remote-ref helpers"],"tags":["git","refs","validation"],"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"}