{"record":{"id":"a7e611063b0cda41","repo":"passbolt/passbolt_api","slug":"the-comment-does-not-exist","errorCode":null,"errorMessage":"The comment does not exist.","messagePattern":"The comment does not exist\\.","errorType":"http","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"src/Service/Comments/CommentsDeleteService.php","lineNumber":69,"sourceCode":"     */\n    public function delete(string $id, ?string $userId = null): void\n    {\n        // Check request sanity\n        if (!Validation::uuid($id)) {\n            throw new BadRequestException(__('The comment id is not valid.'));\n        }\n        if (is_null($userId) || empty($userId)) {\n            throw new BadRequestException(__('The comment userId is not valid.'));\n        }\n\n        // Retrieve the comment.\n        try {\n            /**\n             * @var \\App\\Model\\Entity\\Comment $comment\n             */\n            $comment = $this->Comments->get($id);\n        } catch (RecordNotFoundException $e) {\n            throw new NotFoundException(__('The comment does not exist.'));\n        }\n\n        // Delete the comment.\n        $this->Comments->delete($comment, ['Comments.user_id' => $userId]);\n        $this->_handleDeleteErrors($comment);\n    }\n\n    /**\n     * Manage delete errors\n     *\n     * @param \\App\\Model\\Entity\\Comment $comment comment\n     * @return void\n     */\n    private function _handleDeleteErrors(Comment $comment): void\n    {\n        $errors = $comment->getErrors();\n        if (!empty($errors)) {\n            if (isset($errors['user_id']['is_owner'])) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/Comments/CommentsDeleteService.php#L51-L87","documentation":"CommentsDeleteService::delete() catches RecordNotFoundException from CommentsTable::get($id) and converts it to a 404 NotFoundException. This means no comment row exists with the given UUID — the id was well-formed but references nothing.","triggerScenarios":"DELETE /comments/{uuid} where the comment was already deleted, the id was mistyped as a different UUID, or the id comes from another environment/database.","commonSituations":"Double-delete races (two UI tabs deleting the same comment); stale client caches listing already-removed comments; ids copied from API logs of a different instance.","solutions":["Refetch the comment list to confirm the comment still exists before deleting.","Treat HTTP 404 as success in idempotent delete flows (the target state — comment gone — is already achieved).","Verify the id against the database if you believe the comment should exist."],"exampleFix":"// before\nawait api.delete(`/comments/${id}`); // crashes on 404\n// after\ntry { await api.delete(`/comments/${id}`); } catch (e) { if (e.status !== 404) throw e; } // idempotent","handlingStrategy":"try-catch","validationCode":"// Confirm the comment is still listed before deleting:\nconst stillExists = (await listComments(resourceId)).some(c => c.id === commentId);","typeGuard":null,"tryCatchPattern":"try { await deleteComment(id, userId); }\ncatch (e) { if (e.response?.status === 404) { removeFromLocalCache(id); } else throw e; } // treat as already deleted","preventionTips":["Treat 404 on delete as idempotent success","Evict deleted comments from client caches promptly","Avoid double-delete races by disabling delete buttons after first click"],"tags":["http-404","comments","delete"],"backgroundTag":"record-not-found","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}