{"record":{"id":"d654746b4452142e","repo":"gitbutlerapp/gitbutler","slug":"failed-to-update-comment","errorCode":null,"errorMessage":"Failed to update comment: {}","messagePattern":"Failed to update comment: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-github/src/client.rs","lineNumber":951,"sourceCode":"        #[derive(Serialize)]\n        struct CommentBody<'a> {\n            body: &'a str,\n        }\n\n        let url = format!(\n            \"{}/repos/{}/{}/issues/comments/{}\",\n            self.base_url, owner, repo, comment_id\n        );\n\n        let response = self\n            .client\n            .patch(&url)\n            .json(&CommentBody { body })\n            .send()\n            .await?;\n\n        if !response.status().is_success() {\n            bail!(\n                \"Failed to update comment: {}\",\n                response_error(response).await\n            );\n        }\n\n        let comment: GitHubIssueComment = response.json().await?;\n        Ok(comment.into())\n    }\n\n    pub async fn delete_pull_request_comment(\n        &self,\n        owner: &str,\n        repo: &str,\n        comment_id: i64,\n    ) -> Result<()> {\n        let url = format!(\n            \"{}/repos/{}/{}/issues/comments/{}\",\n            self.base_url, owner, repo, comment_id","sourceCodeStart":933,"sourceCodeEnd":969,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-github/src/client.rs#L933-L969","documentation":"This error comes from `GithubClient::update_pull_request_comment`, which PATCHes `/repos/{owner}/{repo}/issues/comments/{comment_id}` with the new markdown body. A non-success status is surfaced as this error, meaning the comment edit was rejected and no `PullRequestComment` is returned.","triggerScenarios":"Any `update_pull_request_comment(owner, repo, comment_id, body)` call whose PATCH returns non-2xx — 404 (comment id does not exist or belongs to another repo), 403 (token lacks write or is rate-limited), 401 (expired/invalid token), 422 (invalid body).","commonSituations":"Editing a comment that was deleted by another user while the UI kept the old id; using an id from a review comment (different endpoint) as an issue-comment id; token lost `repo` scope after regeneration; editing on the wrong fork.","solutions":["Read the status/details in the error message: 404 means the id is wrong or stale, 401/403 means auth.","Refresh the comment id by listing the PR's issue comments before PATCHing.","Verify the token has repository write access and has not expired.","Confirm you are using the `issues/comments` id, not a review-comment id (`pulls/comments`).","Retry after rate-limit reset if `X-RateLimit-Remaining` is 0."],"exampleFix":"// before\nclient.update_pull_request_comment(owner, repo, stale_id, \"edited\").await?; // 404\n// after\nlet comments = client.list_pull_request_comments(owner, repo, pr).await?;\nif let Some(c) = comments.iter().find(|c| c.id == stale_id) {\n    client.update_pull_request_comment(owner, repo, c.id, \"edited\").await?;\n}","handlingStrategy":"try-catch","validationCode":"let comments = client.list_pull_request_comments(owner, repo, pr).await?;\nif !comments.iter().any(|c| c.id == comment_id) {\n    return Err(anyhow!(\"comment {comment_id} does not exist on {owner}/{repo}#{pr}\"));\n}\nif body.trim().is_empty() { return Err(anyhow!(\"comment body must not be empty\")); }","typeGuard":"fn comment_exists(comments: &[PullRequestComment], id: i64) -> bool { comments.iter().any(|c| c.id == id) }","tryCatchPattern":"match client.update_pull_request_comment(owner, repo, comment_id, body).await {\n    Ok(c) => info!(\"comment {} updated\", c.id),\n    Err(e) if e.to_string().contains(\"404\") => warn!(\"comment vanished; skipping edit\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Refresh comment ids from the server before editing.","Do not reuse review-comment ids as issue-comment ids.","Check token expiry and scope periodically in long sessions.","Validate the body is non-empty before PATCHing."],"tags":["github-api","http-error-response","rest","network"],"backgroundTag":"http-error-response","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"}