fix(comments): return correct status codes for comment reactions - #254
Conversation
AddReaction mapped every error to 409 and echoed the raw err.Error() to the client; RemoveReaction turned every failure into a generic 500. Both now switch on the service's sentinel errors: a duplicate reaction is 409, a missing comment or no-access is 404, and only genuinely unexpected errors are 500 — matching the mapping the other handlers use. The service also translates the unique-constraint violation to ErrReactionExists instead of leaking the raw DB error. Closes #146 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Strix Security ReviewNo security issues found. Updated for Reviewed by Strix |
📝 WalkthroughWalkthroughRefactors comment reaction error handling: ChangesReaction Error Handling
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant CommentHandler
participant CommentService
Client->>CommentHandler: POST AddReaction
CommentHandler->>CommentService: AddReaction(userID, commentID, emoji)
CommentService-->>CommentHandler: ErrReactionExists / not-found error / other error
alt ErrReactionExists
CommentHandler-->>Client: 409 Conflict
else commentAccessNotFound(err)
CommentHandler-->>Client: 404 Not Found
else other error
CommentHandler-->>Client: 500 Internal Server Error
end
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/api/internal/handler/comment_reaction_test.go (1)
36-55: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winGood coverage for the documented cases; consider also asserting the same-emoji conflict path for removal parity.
Coverage nicely mirrors
AddReaction's tests (create/remove happy path + missing-comment 404). One gap: there's no test for removing a reaction that never existed on an otherwise-valid comment (e.g., calling DELETE with an emoji the user never reacted with) — if the store'sRemovetreats "no matching row" as a no-op success rather than an error, the current 404 branch here would never engage for that scenario, worth confirming this is intentional (idempotent removal) rather than an untested gap.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/api/internal/handler/comment_reaction_test.go` around lines 36 - 55, The remove-reaction coverage in Comment_RemoveReaction_StatusCodes is missing the case where the comment exists but the requested emoji reaction was never created. Add an assertion in this test (or a nearby reaction removal test) that calls DELETE on a valid comment with a non-existent emoji and verify the intended behavior, using AddReaction/RemoveReaction and the reactions endpoint helpers to confirm whether removal is intentionally idempotent or should return an error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@apps/api/internal/handler/comment_reaction_test.go`:
- Around line 36-55: The remove-reaction coverage in
Comment_RemoveReaction_StatusCodes is missing the case where the comment exists
but the requested emoji reaction was never created. Add an assertion in this
test (or a nearby reaction removal test) that calls DELETE on a valid comment
with a non-existent emoji and verify the intended behavior, using
AddReaction/RemoveReaction and the reactions endpoint helpers to confirm whether
removal is intentionally idempotent or should return an error.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f9a87fd1-95f5-4c75-bb79-445977a524e2
📒 Files selected for processing (3)
apps/api/internal/handler/comment.goapps/api/internal/handler/comment_reaction_test.goapps/api/internal/service/comment.go
What
Closes #146.
CommentHandler.AddReactionmapped every error to HTTP 409 and echoed the rawerr.Error()back to the client, so a missing comment, a permission failure, or a DB error all looked like a duplicate-reaction conflict and leaked internal strings.RemoveReactionhad the inverse problem: every failure became a generic 500.How
AddReactionnow switches on the service's sentinel errors:ErrReactionExists→ 409 ("Already reacted"), a not-found / no-access error → 404, everything else → 500 with a generic message. No more rawerr.Error()leakage.RemoveReactionreturns 404 for not-found / no-access and only 500 for genuinely unexpected failures.CommentService.AddReactiontranslates the unique-constraint violation toErrReactionExists(mirroring the issue-reaction service) instead of returning the raw GORM error.commentAccessNotFoundhelper so both handlers share the same not-found mapping as the rest of the comment handlers.Testing
New
internal/handler/comment_reaction_test.go:go test ./internal/handler ./internal/servicegreen.AI assistance
Produced with the help of Claude Code (Claude Opus 4.8). AI-assisted commits carry a
Co-Authored-Bytrailer.Summary by CodeRabbit
Bug Fixes
404 Not Foundfor missing or inaccessible comments,409 Conflictfor duplicate reactions, and500only for unexpected failures.404 Not Foundinstead of a generic server error.Tests