From 81513313750f08130b0622b0a483b96cee95796f Mon Sep 17 00:00:00 2001 From: Dotta Date: Fri, 6 Mar 2026 10:58:22 -0600 Subject: [PATCH] Enrich 500 error logs with request context and actual error messages - pino-http customErrorMessage now includes the real error message - customProps includes reqBody, reqParams, reqQuery, and routePath for 4xx/5xx - Error handler logs full request context (body, params, query) for both HttpError 500s and unhandled errors Co-Authored-By: Claude Opus 4.6 --- server/src/middleware/error-handler.ts | 24 +++++++++++++++++++++++- server/src/middleware/logger.ts | 24 +++++++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/server/src/middleware/error-handler.ts b/server/src/middleware/error-handler.ts index b8986c6b..7cf81678 100644 --- a/server/src/middleware/error-handler.ts +++ b/server/src/middleware/error-handler.ts @@ -12,6 +12,21 @@ export function errorHandler( if (err instanceof HttpError) { if (err.status >= 500) { (res as any).err = err; + logger.error( + { + err: { message: err.message, stack: err.stack, name: err.name, details: err.details }, + method: req.method, + url: req.originalUrl, + reqBody: req.body, + reqParams: req.params, + reqQuery: req.query, + }, + "HttpError %d: %s %s — %s", + err.status, + req.method, + req.originalUrl, + err.message, + ); } res.status(err.status).json({ error: err.message, @@ -35,7 +50,14 @@ export function errorHandler( (res as any).err = realError; logger.error( - { err: errObj, method: req.method, url: req.originalUrl }, + { + err: errObj, + method: req.method, + url: req.originalUrl, + reqBody: req.body, + reqParams: req.params, + reqQuery: req.query, + }, "Unhandled error: %s %s — %s", req.method, req.originalUrl, diff --git a/server/src/middleware/logger.ts b/server/src/middleware/logger.ts index 2f7da6dd..4c018138 100644 --- a/server/src/middleware/logger.ts +++ b/server/src/middleware/logger.ts @@ -52,10 +52,28 @@ export const httpLogger = pinoHttp({ customSuccessMessage(req, res) { return `${req.method} ${req.url} ${res.statusCode}`; }, - customErrorMessage(req, res) { - return `${req.method} ${req.url} ${res.statusCode}`; + customErrorMessage(req, res, err) { + const errMsg = err?.message || (res as any).err?.message || "unknown error"; + return `${req.method} ${req.url} ${res.statusCode} — ${errMsg}`; }, - customProps() { + customProps(req, res) { + if (res.statusCode >= 400) { + const props: Record = {}; + const { body, params, query } = req as any; + if (body && typeof body === "object" && Object.keys(body).length > 0) { + props.reqBody = body; + } + if (params && typeof params === "object" && Object.keys(params).length > 0) { + props.reqParams = params; + } + if (query && typeof query === "object" && Object.keys(query).length > 0) { + props.reqQuery = query; + } + if ((req as any).route?.path) { + props.routePath = (req as any).route.path; + } + return props; + } return {}; }, });