{"record":{"id":"d2419792a5ac1931","repo":"TryGhost/Ghost","slug":"failed-to-dislike-comment","errorCode":null,"errorMessage":"Failed to dislike comment","messagePattern":"Failed to dislike comment","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/comments-ui/src/utils/api.ts","lineNumber":318,"sourceCode":"                        return 'Success';\n                    } else {\n                        throw new Error('Failed to unlike comment');\n                    }\n                });\n            },\n            dislike({comment}: {comment: {id: string}}) {\n                const url = endpointFor({type: 'members', resource: `comments/${comment.id}/dislike`});\n                return makeRequest({\n                    url,\n                    method: 'POST',\n                    headers: {\n                        'Content-Type': 'application/json'\n                    }\n                }).then(function (res) {\n                    if (res.ok) {\n                        return 'Success';\n                    } else {\n                        throw new Error('Failed to dislike comment');\n                    }\n                });\n            },\n            undislike({comment}: {comment: {id: string}}) {\n                const body = {\n                    comments: [comment]\n                };\n                const url = endpointFor({type: 'members', resource: `comments/${comment.id}/dislike`});\n                return makeRequest({\n                    url,\n                    method: 'DELETE',\n                    headers: {\n                        'Content-Type': 'application/json'\n                    },\n                    body: JSON.stringify(body)\n                }).then(function (res) {\n                    if (res.ok) {\n                        return 'Success';","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/apps/comments-ui/src/utils/api.ts#L300-L336","documentation":"comments.dislike() POSTs to /members/api/comments/{comment.id}/dislike to register a dislike reaction. Mirrors the like() structure: returns 'Success' on ok, throws on non-ok, no body sent. Dislike is a labs-gated feature in Ghost comments.","triggerScenarios":"The POST returns 4xx/5xx. The member is unauthenticated (401), already disliked (409/400), the comment was deleted (404), the labs flag for dislikes is disabled (403), or rate limited (429).","commonSituations":"A member dislikes a comment but the site admin disabled the dislike labs feature after the UI rendered the button. Session expiry. A double-click submits two dislikes.","solutions":["Check the Network tab POST response status and body.","Gate the dislike button visibility on the labs flag returned by site.settings() to avoid 403s.","Optimistically update and revert on error; disable the button during the request.","If 401, re-authenticate; if 403, hide the dislike UI and refresh settings."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isDislikesEnabled(labs: {dislikes?: boolean} | undefined): boolean {\n  return Boolean(labs?.dislikes);\n}","typeGuard":null,"tryCatchPattern":"setDisliked(true);\ntry {\n  await api.comments.dislike({comment});\n} catch (e) {\n  setDisliked(false);\n  if (e instanceof Error && e.message === 'Failed to dislike comment') {\n    // if 403, dislikes may be disabled — refresh labs\n  }\n}","preventionTips":["Gate the dislike button on the labs flag from site.settings() to avoid 403s.","Disable the button during the POST; use optimistic UI with rollback.","Refresh site settings if a 403 occurs, since the labs flag may have changed."],"tags":["network","fetch","comments-ui","dislike","reaction","labs"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}