Skip to content

feat: standardise the error response envelope helper (#739) - #852

Open
Obiajulu-gif wants to merge 1 commit into
accesslayerorg:mainfrom
Obiajulu-gif:feat/739-error-response-envelope-helper
Open

feat: standardise the error response envelope helper (#739)#852
Obiajulu-gif wants to merge 1 commit into
accesslayerorg:mainfrom
Obiajulu-gif:feat/739-error-response-envelope-helper

Conversation

@Obiajulu-gif

Copy link
Copy Markdown
Contributor

Summary

buildErrorResponse(code, message, details?) already existed in lib/utils/api-response.utils.ts with the exact requested shape — { error: { code, message, details? } }, details omitted when not provided/empty — but two things from the issue were still missing:

  1. Empty string code validation. buildErrorResponse now throws InvalidErrorCode when called with an empty string code.
  2. Consistent usage. Several handlers and middleware still built their own inline { success: false, ... } objects instead of calling the helper, so the envelope shape wasn't actually consistent across all endpoints yet.

Changes

  • buildErrorResponse throws InvalidErrorCode for an empty code, with a new unit test alongside the existing with/without-details coverage.
  • Replaced every remaining inline error-object construction with the shared helper:
    • error.middleware.ts: JWT error, TokenExpired, Prisma error, ApiError catch, oversized-payload (413), malformed-JSON (400) branches
    • body-parse-error.middleware.ts: both its 413 and 400 branches
    • ledger.controllers.ts and health.controllers.ts: catch-all 500s
    • admin.controllers.ts: the indexer-replay lock-conflict 409
    • auth.controllers.ts: the refresh-token 401s — their old lowercase code: 'invalid_token'/code: result.code strings now live in details instead, since the envelope's code field is the shared ErrorCode vocabulary
  • Left mapUnknownRouteError (route-error.utils.ts) alone — it's the deliberate last-resort fallback with its own debug-mode stack/raw-error fields and already-factored tests, not an inline inconsistency to clean up.
  • Left the internal (non-HTTP-response) { success: false, ... } return values in token-refresh.utils.ts and stellar-submit.utils.ts alone — they're not API response bodies.
  • Updated the two affected test files (ledger.controllers.test.ts, body-parse-error.middleware.test.ts) for the new nested error shape.

Acceptance Criteria

  • Envelope shape { error: { code, message } } consistent across all endpoints
  • details absent when not provided
  • Empty string code throws InvalidErrorCode
  • All existing inline error objects replaced with the helper

Test plan

  • tsc --noEmit is clean on every file this PR touches (repo has ~30 pre-existing unrelated errors elsewhere — missing Prisma models, redis nullability, etc. — none overlapping this change)
  • Ran every test file covering the touched code: api-response.utils, ledger.controllers, body-parse-error.middleware, error.middleware, admin.controllers, health — 125/125 passing

Closes #739

)

lib/utils/api-response.utils.ts already had a `buildErrorResponse(code,
message, details?)` helper matching the requested `{ error: { code,
message, details? } }` shape (details already omitted when not
provided/empty), but two pieces were missing and several handlers still
built their own ad-hoc error objects:

- buildErrorResponse now throws InvalidErrorCode for an empty string
  code, with a unit test for it, alongside the existing with/without-
  details coverage.
- Replaced every remaining inline `{ success: false, ... }` /
  `{ success: false, code, message }` construction in route handlers and
  middleware with the shared helper (via buildErrorResponse directly or
  the sendError wrapper): error.middleware.ts's JWT/TokenExpired/Prisma/
  ApiError/oversized-payload/malformed-JSON branches,
  body-parse-error.middleware.ts, ledger.controllers.ts and
  health.controllers.ts's catch-all 500s, admin.controllers.ts's lock-
  conflict 409, and auth.controllers.ts's refresh-token 401s (whose
  ad-hoc lowercase `code: 'invalid_token'` strings are now carried in
  `details` instead, since the envelope's `code` field is the shared
  ErrorCode vocabulary).
- Left mapUnknownRouteError (route-error.utils.ts) as-is — it's the
  deliberate last-resort fallback with its own debug-mode stack/raw-
  error fields and already-factored tests, not an inline inconsistency.
  Also left the internal (non-HTTP-response) `{success: false, ...}`
  return values in token-refresh.utils.ts and stellar-submit.utils.ts
  alone since they aren't API response bodies.

Updated the two affected test files (ledger.controllers.test.ts,
body-parse-error.middleware.test.ts) for the new nested error shape.

Verification: `tsc --noEmit` is clean on every file this PR touches (the
repo has ~30 pre-existing unrelated errors on other files — missing
Prisma models/redis nullability/etc — none overlapping this change).
Ran the full test files covering everything touched:
api-response.utils, ledger.controllers, body-parse-error.middleware,
error.middleware, admin.controllers, health — 125/125 passing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add helper for building a standardised error response envelope used consistently across all endpoints

1 participant