fix(api): map backend errors to 400/404 instead of 500 (EN-1227) - #190
fix(api): map backend errors to 400/404 instead of 500 (EN-1227)#190flemzord wants to merge 1 commit into
Conversation
Most read/write handlers mapped every backend error to 500, and the trigger/workflow create+test handlers returned 500 for malformed request bodies. Unknown ids therefore looked like server faults and bad client payloads were misclassified. - Add api.WriteError(), mapping sql.ErrNoRows, the workflow not-found sentinels and Temporal NotFound to 404, ErrInvalidConfig to 400, and everything else to 500. Use it in readInstance, readWorkflow, runWorkflow, postEvent, abortWorkflowInstance, readInstanceHistory and testTrigger (v1 + v2). - createTrigger / testTrigger: malformed body -> 400 (was 500). - createWorkflow: wrap validation failures as workflow.ErrInvalidConfig so they surface as 400; drop two panics (post-wait GetInstance, json.Marshal) in favour of returned error responses. Tests: TestGetInstanceNotFound (404) and TestCreateWorkflowValidationError (400). Note: edits internal/workflow/manager.go (Create + new sentinel) and many v1/v2 handlers shared with other PRs in this series; independent, different regions.
WalkthroughThis PR refactors API error handling to intelligently classify backend errors and map them to appropriate HTTP responses. A new ChangesAPI Error Handling Infrastructure and Refactoring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
internal/api/errors.go (1)
13-31: ⚡ Quick winAdd direct branch-level tests for the error mapper.
This helper now defines core API status semantics. Please add table-driven unit tests that exercise each branch (
sql.ErrNoRows,workflow.ErrInstanceNotFound,workflow.ErrWorkflowNotFound, TemporalNotFound,workflow.ErrInvalidConfig, and default 500) to prevent silent regressions across handlers.🤖 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 `@internal/api/errors.go` around lines 13 - 31, Add table-driven unit tests for WriteError that exercise each branch: provide inputs of sql.ErrNoRows, workflow.ErrInstanceNotFound, workflow.ErrWorkflowNotFound, a Temporal NotFound (serviceerror.NotFound{}), workflow.ErrInvalidConfig, and a generic error for the default case. For each case call WriteError with an httptest.ResponseRecorder and a dummy *http.Request and assert the resulting HTTP status and/or body matches the expected handler (sharedapi.NotFound -> 404, sharedapi.BadRequest -> 400 with "VALIDATION" code, sharedapi.InternalServerError -> 500). Name the test function TestWriteError_TableDriven and place cases in a slice with descriptive names so any failure shows which branch regressed; use the same identifiers WriteError, workflow.ErrInstanceNotFound, workflow.ErrWorkflowNotFound, workflow.ErrInvalidConfig, sql.ErrNoRows, and serviceerror.NotFound to locate the logic under test.
🤖 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 `@internal/api/errors.go`:
- Around line 13-31: Add table-driven unit tests for WriteError that exercise
each branch: provide inputs of sql.ErrNoRows, workflow.ErrInstanceNotFound,
workflow.ErrWorkflowNotFound, a Temporal NotFound (serviceerror.NotFound{}),
workflow.ErrInvalidConfig, and a generic error for the default case. For each
case call WriteError with an httptest.ResponseRecorder and a dummy *http.Request
and assert the resulting HTTP status and/or body matches the expected handler
(sharedapi.NotFound -> 404, sharedapi.BadRequest -> 400 with "VALIDATION" code,
sharedapi.InternalServerError -> 500). Name the test function
TestWriteError_TableDriven and place cases in a slice with descriptive names so
any failure shows which branch regressed; use the same identifiers WriteError,
workflow.ErrInstanceNotFound, workflow.ErrWorkflowNotFound,
workflow.ErrInvalidConfig, sql.ErrNoRows, and serviceerror.NotFound to locate
the logic under test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 18477be9-0d2f-46e7-93a8-fa7089f405d8
📒 Files selected for processing (21)
internal/api/errors.gointernal/api/v1/handler_abort_workflow_instance.gointernal/api/v1/handler_create_trigger.gointernal/api/v1/handler_create_workflow.gointernal/api/v1/handler_post_event.gointernal/api/v1/handler_read_instance.gointernal/api/v1/handler_read_instance_history.gointernal/api/v1/handler_read_workflow.gointernal/api/v1/handler_run_workflow.gointernal/api/v2/handler_abort_workflow_instance.gointernal/api/v2/handler_create_trigger.gointernal/api/v2/handler_create_workflow.gointernal/api/v2/handler_create_workflow_test.gointernal/api/v2/handler_post_event.gointernal/api/v2/handler_read_instance.gointernal/api/v2/handler_read_instance_history.gointernal/api/v2/handler_read_instance_test.gointernal/api/v2/handler_read_workflow.gointernal/api/v2/handler_run_workflow.gointernal/api/v2/handler_test_trigger.gointernal/workflow/manager.go
|
Superseded by #199, which consolidates this change with the related reliability and safety fixes on top of the current main branch. |
Problem (H7 + H8 — HIGH)
readInstance,readWorkflow,runWorkflow,postEvent,abortWorkflowInstance,readInstanceHistory) returned 500 instead of 404, contradicting the spec and creating alerting noise.createTrigger/testTriggerreturned 500 for a malformed JSON body, andcreateWorkflowreturned 500 for config-validation failures (andpaniced on a post-waitGetInstanceand ajson.Marshal).Fix
api.WriteError(w, r, err)central mapper:sql.ErrNoRows+ workflow not-found sentinels + TemporalNotFound⇒ 404;workflow.ErrInvalidConfig⇒ 400; otherwise 500. Used across the read/run/post/abort/history/test handlers (v1 + v2).createTrigger/testTrigger: malformed body ⇒ 400.createWorkflow:Createnow wraps validation errors asworkflow.ErrInvalidConfig(⇒ 400); bothpanics replaced with proper error responses.Tests
TestGetInstanceNotFound(404) andTestCreateWorkflowValidationError(400).Severity: HIGH.