{"record":{"id":"61264495a0f740ab","repo":"gitbutlerapp/gitbutler","slug":"review-thread-replies-for-forge-forge-are-not-implemented","errorCode":null,"errorMessage":"Review thread replies for forge {forge:?} are not implemented yet.","messagePattern":"Review thread replies for forge (.+?) are not implemented yet\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-forge/src/review.rs","lineNumber":1802,"sourceCode":"    thread_id: &str,\n    body: &str,\n    storage: &but_forge_storage::Controller,\n) -> Result<ForgeReviewThreadComment> {\n    let crate::forge::ForgeRepoInfo { forge, .. } = 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::create_review_thread_reply(\n                preferred_account,\n                thread_id,\n                body,\n                storage,\n            )\n            .await?;\n            Ok(comment.into())\n        }\n        // A write, so it fails loudly rather than reading as empty.\n        _ => Err(anyhow::anyhow!(\n            \"Review thread replies for forge {forge:?} are not implemented yet.\"\n        )),\n    }\n}\n\n/// List the diff-anchored review threads on a review, oldest first. Each\n/// call hits the forge fresh (no DB cache).\npub async fn list_review_threads(\n    preferred_forge_user: &Option<crate::ForgeUser>,\n    forge_repo_info: &crate::forge::ForgeRepoInfo,\n    review_number: usize,\n    storage: &but_forge_storage::Controller,\n) -> Result<Vec<ForgeReviewThread>> {\n    let crate::forge::ForgeRepoInfo {\n        forge, owner, repo, ..\n    } = forge_repo_info;\n    match forge {\n        ForgeName::GitHub => {","sourceCodeStart":1784,"sourceCodeEnd":1820,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-forge/src/review.rs#L1784-L1820","documentation":"The review-thread reply API in but-forge only implements posting a reply for GitHub; the wildcard match arm returns this error for any other forge. It is an explicit 'write operation unsupported on this forge' guard so callers never assume a reply was created when it was not.","triggerScenarios":"Replying to an existing review thread via the reply-into-thread function while the repository's ForgeName is GitLab, Bitbucket, or Azure.","commonSituations":"A developer or user connected to a GitLab merge request, Bitbucket PR, or Azure PR tries to comment on a review thread through the GitButler forge abstraction; or a newly onboarded forge got read paths wired up before the write path for replies.","solutions":["Restrict thread replies to GitHub repositories and surface an 'unsupported on this forge' message in the UI otherwise.","Gate the reply API call on ForgeName::GitHub before invoking it.","Implement the reply arm for the target forge in crates/but-forge/src/review.rs or wait for upstream forge support."],"exampleFix":"// before\nlet comment = forge::reply_review_thread(forge, review_number, thread_id, body, storage).await?;\n\n// after\nif forge != ForgeName::GitHub {\n    eprintln!(\"thread replies are not supported for this forge\");\n    return Ok(());\n}\nlet comment = forge::reply_review_thread(forge, review_number, thread_id, body, storage).await?;","handlingStrategy":"fallback","validationCode":"if (forge !== 'github') { throw new SkipOperation(`thread replies unsupported for ${forge}`); }","typeGuard":"const isGitHub = (forge: ForgeName): forge is 'github' => forge === 'github';","tryCatchPattern":"try { await replyToThread(...) } catch (e) { if (String(e).includes('not implemented yet')) { disableReplyComposer(); } else { throw e; } }","preventionTips":["Gate write operations (replies, reactions, comments) on GitHub repos only","Hide reply UI for non-GitHub forges instead of attempting the call","Add an integration test asserting non-GitHub forges fail loudly rather than no-op"],"tags":["forge","review-thread","unimplemented"],"backgroundTag":"method-not-implemented","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"}