{"record":{"id":"d95b2944cd0b701a","repo":"gitbutlerapp/gitbutler","slug":"review-requests-for-forge-forge-are-not-implem","errorCode":null,"errorMessage":"Review requests for forge {forge:?} are not implemented yet.","messagePattern":"Review requests for forge (.+?) are not implemented yet\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-forge/src/review.rs","lineNumber":1230,"sourceCode":"    storage: &but_forge_storage::Controller,\n) -> Result<()> {\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            but_github::pr::request_reviewers(\n                preferred_account,\n                owner,\n                repo,\n                review_number,\n                logins,\n                storage,\n            )\n            .await\n        }\n        _ => Err(anyhow::anyhow!(\n            \"Review requests for forge {forge:?} are not implemented yet.\"\n        )),\n    }\n}\n\n/// Withdraw review requests for the given users on a review.\npub async fn withdraw_review_request(\n    preferred_forge_user: &Option<crate::ForgeUser>,\n    forge_repo_info: &crate::forge::ForgeRepoInfo,\n    review_number: usize,\n    logins: &[String],\n    storage: &but_forge_storage::Controller,\n) -> Result<()> {\n    let crate::forge::ForgeRepoInfo {\n        forge, owner, repo, ..\n    } = forge_repo_info;\n    match forge {\n        ForgeName::GitHub => {","sourceCodeStart":1212,"sourceCodeEnd":1248,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-forge/src/review.rs#L1212-L1248","documentation":"`request_review()` asks specific users to review a review (PR/MR). Only the GitHub backend is wired (via `but_github::pr::request_reviewers`); other forges fall into the wildcard arm and fail before any network call.","triggerScenarios":"Calling `request_review` with a list of logins for a review hosted on GitLab, Bitbucket or Azure — typically the submit action of a reviewer picker on a non-GitHub repo.","commonSituations":"Reviewer-request flows built against GitHub and reused across forges; multi-forge UIs where the button is visible everywhere; SDK automations that request reviews programmatically.","solutions":["Request reviewers through the forge's own UI/API for non-GitHub reviews.","Gate the request action on `forge == ForgeName::GitHub`.","Implement reviewer-request calls in `but_gitlab`/`but_bitbucket` and extend the match at crates/but-forge/src/review.rs:1222-1230."],"exampleFix":"// before\nrequest_review(&user, &info, number, &[\"alice\".into()], &storage).await?;\n\n// after\nif !matches!(info.forge, ForgeName::GitHub) {\n    return Ok(()); // reviewer requests are GitHub-only\n}\nrequest_review(&user, &info, number, &[\"alice\".into()], &storage).await?;","handlingStrategy":"validation","validationCode":"use but_forge::forge::ForgeName;\n\nif !matches!(info.forge, ForgeName::GitHub) {\n    // hide 'request review' submit; only GitHub implements it\n}","typeGuard":"fn review_requests_supported(forge: &but_forge::forge::ForgeName) -> bool {\n    matches!(forge, ForgeName::GitHub)\n}","tryCatchPattern":"match request_review(&user, &info, number, logins, &storage).await {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"not implemented yet\") => { /* no-op; inform user */ }\n    Err(e) => return Err(e),\n}","preventionTips":["Disable the whole reviewer-request flow (list + request + withdraw) behind one forge check.","Don't fire the request call as part of a fire-and-forget queue on non-GitHub forges.","Track which review mutations exist per forge in a capability module, not in scattered ifs."],"tags":["rust","but-forge","code-review","reviewers","pull-request","github","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"}