Skip to content

unify api error response shape

jedmund requested to merge jedmund/arch-audit-error-shape into main

Created by: jedmund

Summary

Architecture audit A-1 — collapse the two competing API error shapes into one.

Every errorResponse() call now emits { error: { code, message, details? } } where code is a symbolic name derived from the HTTP status (e.g. 401 → UNAUTHORIZED, 404 → NOT_FOUND, 500 → INTERNAL_ERROR). Clients get a consistent, self-describing shape and a stable place to attach validation details.

  • New: src/lib/server/error-codes.ts — status → code map + codeForStatus() helper
  • Updated: errorResponse(message, status, details?) emits the structured shape. Signature preserved — all ~300 route-side callers keep working unchanged.
  • Updated: hooks.server.ts unauth response aligned to the same shape.
  • Updated: 7 admin client fetch consumers now read errorData.error?.message. Three of them were reading .error as a string (will-break path). Four were silently broken (reading top-level .message that the old shape didn't emit either) — these now actually surface error messages.

Public pages that read data.error from +page.server.ts loaders are unaffected (loader-set strings, not API responses). Tags routes' bespoke json({error: {code, message, field, details}}) calls already match the new shape. Success response bodies unchanged.

Test plan

  • pnpm check — baseline 116 errors / 9 warnings, no new ones
  • curl -I unauthenticated GET /api/admin/media-stats → body is {"error":{"code":"UNAUTHORIZED","message":"Unauthorized"}}
  • POST /api/posts with invalid JSON → {"error":{"code":"BAD_REQUEST","message":"..."}}
  • Delete an album from the admin UI while logged out → status message shows "Unauthorized" (not undefined)
  • Upload a file that fails server validation via ImageUploader → toast shows the actual error message
  • Tag with reserved name → admin TagInput still shows the TAG_NAME_RESERVED message (tags route keeps its bespoke shape)

Merge request reports

Loading