{"record":{"id":"0e812f3f542dc40f","repo":"gitbutlerapp/gitbutler","slug":"review-comments-for-forge-forge-are-not-implem","errorCode":null,"errorMessage":"Review comments for forge {forge:?} are not implemented yet.","messagePattern":"Review comments for forge (.+?) are not implemented yet\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-forge/src/review.rs","lineNumber":1330,"sourceCode":") -> Result<ForgeReviewComment> {\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 comment = but_github::pr::update_comment(\n                preferred_account,\n                owner,\n                repo,\n                comment_id,\n                body,\n                storage,\n            )\n            .await?;\n            Ok(comment.into())\n        }\n        _ => Err(anyhow::anyhow!(\n            \"Review comments for forge {forge:?} are not implemented yet.\"\n        )),\n    }\n}\n\n/// Delete a top-level conversation comment.\npub async fn delete_review_comment(\n    preferred_forge_user: &Option<crate::ForgeUser>,\n    forge_repo_info: &crate::forge::ForgeRepoInfo,\n    comment_id: i64,\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 => {\n            let preferred_account = preferred_forge_user.as_ref().and_then(|user| user.github());","sourceCodeStart":1312,"sourceCodeEnd":1348,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-forge/src/review.rs#L1312-L1348","documentation":"Editing a top-level conversation comment goes through `update_review_comment()`. Only GitHub is implemented (via `but_github::pr::update_comment`, which returns the updated comment); GitLab, Bitbucket and Azure hit the wildcard arm and fail before any request is sent.","triggerScenarios":"The 'edit' action on a conversation comment for a review hosted on GitLab, Bitbucket or Azure — any `update_review_comment` call with a `comment_id` where `forge` is not GitHub.","commonSituations":"Comment edit buttons rendered for all forges; SDK consumers assuming comment CRUD parity across forges.","solutions":["Edit the comment through the forge's web UI or native API.","Show edit as disabled for non-GitHub forges.","Implement a comment-update backend in `but_gitlab`/`but_bitbucket` and extend the match at crates/but-forge/src/review.rs:1322-1330."],"exampleFix":"// before\nupdate_review_comment(&user, &info, comment_id, &new_body, &storage).await?;\n\n// after\nif !matches!(info.forge, ForgeName::GitHub) {\n    return Ok(Default::default()); // comment editing is GitHub-only; hide the control\n}\nupdate_review_comment(&user, &info, comment_id, &new_body, &storage).await?;","handlingStrategy":"validation","validationCode":"use but_forge::forge::ForgeName;\n\nif !matches!(info.forge, ForgeName::GitHub) {\n    // render comment as read-only; editing is GitHub-only\n}","typeGuard":"fn comment_edit_supported(forge: &but_forge::forge::ForgeName) -> bool {\n    matches!(forge, ForgeName::GitHub)\n}","tryCatchPattern":"match update_review_comment(&user, &info, comment_id, body, &storage).await {\n    Ok(comment) => comment,\n    Err(e) if e.to_string().contains(\"not implemented yet\") => { /* keep old body */ return Ok(Default::default()); }\n    Err(e) => return Err(e),\n}","preventionTips":["Gate comment mutation buttons (edit/delete) on the forge before rendering.","Never pre-apply the edited body in the UI before the call succeeds on unsupported forges.","Cover comment CRUD per forge in contract tests."],"tags":["rust","but-forge","comments","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"}