@@ -2,6 +2,7 @@ import express from 'express';
22import logger from '../utils/logger' ;
33import { captureException } from '../utils/errorTracker' ;
44import { sanitizeString , sanitizeUrl , sanitizeDescription } from '../utils/sanitize' ;
5+ import { AppError } from '../utils/asyncRouteHandler' ;
56
67export interface ClientErrorRequestBody {
78 message : string ;
@@ -52,13 +53,42 @@ export const handleClientError = (req: express.Request, res: express.Response) =
5253 res . status ( 202 ) . json ( { success : true , message : 'Client error logged' } ) ;
5354} ;
5455
56+ /**
57+ * Centralized error-handling middleware.
58+ *
59+ * Handles:
60+ * - AppError instances — use the embedded statusCode and extra payload.
61+ * - UnauthorizedError (from express-jwt / similar).
62+ * - CORS errors.
63+ * - Everything else → 500 Internal Server Error.
64+ *
65+ * All responses follow the standardized shape:
66+ * { success: false, error: "<message>", requestId?: "<uuid>" }
67+ */
5568export const apiErrorHandler : express . ErrorRequestHandler = ( err , req , res , next ) => {
5669 if ( res . headersSent ) {
5770 return next ( err ) ;
5871 }
5972
6073 const requestId = ( req as any ) . requestId as string | undefined ;
6174
75+ // ── Known error types ────────────────────────────────────
76+
77+ if ( err instanceof AppError ) {
78+ const body : Record < string , unknown > = {
79+ success : false ,
80+ error : err . message ,
81+ } ;
82+ if ( requestId ) body . requestId = requestId ;
83+ // Merge extra fields (e.g. errors[], rateLimitInfo, providerId)
84+ if ( err . extra ) {
85+ for ( const [ key , value ] of Object . entries ( err . extra ) ) {
86+ body [ key ] = value ;
87+ }
88+ }
89+ return res . status ( err . statusCode ) . json ( body ) ;
90+ }
91+
6292 if ( err ?. name === 'UnauthorizedError' ) {
6393 return res . status ( 401 ) . json ( { success : false , error : 'Unauthorized' , requestId } ) ;
6494 }
@@ -67,6 +97,8 @@ export const apiErrorHandler: express.ErrorRequestHandler = (err, req, res, next
6797 return res . status ( 403 ) . json ( { success : false , error : 'CORS policy violation' , requestId } ) ;
6898 }
6999
100+ // ── Unhandled errors (500) ───────────────────────────────
101+
70102 logger . error ( 'Unhandled server error' , {
71103 message : err ?. message ,
72104 stack : err ?. stack ,
@@ -84,5 +116,9 @@ export const apiErrorHandler: express.ErrorRequestHandler = (err, req, res, next
84116 requestId,
85117 } ) ;
86118
87- res . status ( 500 ) . json ( { success : false , error : 'Internal server error' , requestId } ) ;
119+ res . status ( 500 ) . json ( {
120+ success : false ,
121+ error : 'Internal server error' ,
122+ ...( requestId ? { requestId } : { } ) ,
123+ } ) ;
88124} ;
0 commit comments