fix: return JSON on unhandled errors (no more HTML 500)#29
Merged
AdaInTheLab merged 1 commit intomainfrom Apr 30, 2026
Merged
Conversation
… default)
Express's default error handler renders an HTML page for 5xx, which
hides the actual cause from anyone consuming the API as JSON
(browser fetch, CLI, debugging tools). Add a JSON error-handler
middleware as the last app.use() so failures surface as a structured
{ ok: false, error: { code, message, details? } } response.
Behavior:
- Honors err.status / err.statusCode so middleware that throws with a
status (e.g. express-openapi-validator with 400 + .errors[]) lands
as the right code instead of a generic 500
- Maps common statuses to canonical codes (bad_request, unauthorized,
forbidden, not_found, internal_error)
- Surfaces validation .errors[] as `details` for OpenAPI failures
- Includes a trimmed stack outside production (NODE_ENV !== "production")
- Always logs the full error server-side so PM2 logs still show cause
Triggered by a production HTML-500 from POST /admin/notes that gave
no response body to debug from. With this in place, the next failure
will return the actual exception in JSON.
Co-authored-by: Sage <[email protected]>
😼🔥 Carmel Chaos Stamp™🔥 Carmel Chaos Stamp™
This automated judgment has been issued by the Chief Judgment Office (CJO). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Production POST
/admin/notesis returning an HTML500page with no response body, making it impossible to see the actual exception from a JSON client. That happens because Express's default error handler renders HTML when no JSON error middleware intercepts.This PR adds a tiny JSON error-handler at the end of `createApp()` so:
{ ok: false, error: { code, message, details? } }err.status/err.statusCode(notablyexpress-openapi-validator, which throws 400 with an.errors[]array) lands as the right HTTP code with the validation details visibleWhy
The 500s started after #28 landed. Without the error body we can't tell whether the failure is:
author_name/author_kind/tagsfields becauseopenapi.jsonwasn't updated alongside the handlerThis handler will surface the actual cause on the next failed POST.
Testing
npx tsc --noEmit— cleannpm run test— 41/41 passBreaking changes
None for happy-path responses. Error response shape is now JSON instead of HTML — anything that was relying on parsing the HTML 500 page (nothing should be) would break. Worth it.
Next step
Merge + deploy, then re-run the failing POST. The response body will tell us what to fix.
Co-authored-by: Sage [email protected]