{"record":{"id":"b6f46089a1207711","repo":"gitbutlerapp/gitbutler","slug":"repository-labels-for-forge-forge-are-not-impl","errorCode":null,"errorMessage":"Repository labels for forge {forge:?} are not implemented yet.","messagePattern":"Repository labels for forge (.+?) are not implemented yet\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-forge/src/review.rs","lineNumber":1116,"sourceCode":"}\n\n/// List the labels defined on the repository backing a review.\npub async fn list_repo_labels(\n    preferred_forge_user: &Option<crate::ForgeUser>,\n    forge_repo_info: &crate::forge::ForgeRepoInfo,\n    storage: &but_forge_storage::Controller,\n) -> Result<Vec<ForgeReviewLabel>> {\n    let crate::forge::ForgeRepoInfo {\n        forge, owner, repo, ..\n    } = forge_repo_info;\n    match forge {\n        ForgeName::GitHub => {\n            let preferred_account = preferred_forge_user.as_ref().and_then(|user| user.github());\n            let labels =\n                but_github::pr::list_repo_labels(preferred_account, owner, repo, storage).await?;\n            Ok(labels.into_iter().map(Into::into).collect())\n        }\n        _ => Err(anyhow::anyhow!(\n            \"Repository labels for forge {forge:?} are not implemented yet.\"\n        )),\n    }\n}\n\n/// Add labels to a review; returns the resulting label set.\npub async fn add_review_labels(\n    preferred_forge_user: &Option<crate::ForgeUser>,\n    forge_repo_info: &crate::forge::ForgeRepoInfo,\n    review_number: usize,\n    labels: &[String],\n    storage: &but_forge_storage::Controller,\n) -> Result<Vec<ForgeReviewLabel>> {\n    let crate::forge::ForgeRepoInfo {\n        forge, owner, repo, ..\n    } = forge_repo_info;\n    match forge {\n        ForgeName::GitHub => {","sourceCodeStart":1098,"sourceCodeEnd":1134,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-forge/src/review.rs#L1098-L1134","documentation":"but-forge's `list_repo_labels()` dispatches the forge-agnostic 'list repository labels' operation per forge. Only the `ForgeName::GitHub` arm is wired up (it calls `but_github::pr::list_repo_labels`); GitLab, Bitbucket and Azure fall into the wildcard arm, which fails fast with this anyhow error before any network call is made.","triggerScenarios":"Calling `but_forge::review::list_repo_labels` (or any SDK/Tauri/CLI endpoint wrapping it) with `ForgeRepoInfo.forge` set to GitLab, Bitbucket or Azure — for example the label picker opened on a repo whose remote resolves to gitlab.com or bitbucket.org. The GitHub arm never produces this error.","commonSituations":"Assuming every `ForgeName` variant supports the full review API; UI surfaces (label pickers) rendered uniformly for all forges; forge auto-detection from the remote URL selecting a non-GitHub forge; new forge integrations added to the enum without label backends.","solutions":["Use a GitHub-hosted repository — repository labels are GitHub-only in but-forge today.","Gate the caller: hide or skip the label feature when `ForgeRepoInfo.forge` is not `ForgeName::GitHub`.","Implement the backend: add a `but_gitlab::`/`but_bitbucket::` label-listing call and extend the match arm at crates/but-forge/src/review.rs:1108-1116.","Bypass the abstraction and query the forge's native label API directly for non-GitHub repos."],"exampleFix":"// before\nlet labels = but_forge::review::list_repo_labels(&user, &info, &storage).await?;\n\n// after\nlet labels = match info.forge {\n    ForgeName::GitHub => but_forge::review::list_repo_labels(&user, &info, &storage).await?,\n    _ => Vec::new(), // repository labels are GitHub-only; hide the picker\n};","handlingStrategy":"validation","validationCode":"use but_forge::forge::ForgeName;\n\nif !matches!(info.forge, ForgeName::GitHub) {\n    // hide the repository label UI instead of calling list_repo_labels\n}","typeGuard":"fn repo_labels_supported(forge: &but_forge::forge::ForgeName) -> bool {\n    matches!(forge, ForgeName::GitHub)\n}","tryCatchPattern":"match but_forge::review::list_repo_labels(&user, &info, &storage).await {\n    Ok(labels) => labels,\n    Err(e) if e.to_string().contains(\"not implemented yet\") => Vec::new(), // unsupported forge\n    Err(e) => return Err(e),\n}","preventionTips":["Check `ForgeRepoInfo.forge` before calling — but-forge's label, reaction and comment surfaces are GitHub-only; only review CRUD is multi-forge.","Keep a per-forge capability table in UI code instead of assuming uniform feature parity.","When adding a new ForgeName variant, add tests asserting which review functions still return 'not implemented yet'."],"tags":["rust","but-forge","labels","github","gitlab","bitbucket","azure","not-implemented"],"backgroundTag":"not-implemented-for-platform","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}