From f64a0350698459e0502495b19675e2f2701d9a38 Mon Sep 17 00:00:00 2001 From: siddseethepalli Date: Tue, 24 Feb 2026 22:35:58 +0000 Subject: [PATCH] fix: preserve Error name/message/stack in log redaction serializer Co-Authored-By: Claude --- gateway/src/log-redact.ts | 40 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/gateway/src/log-redact.ts b/gateway/src/log-redact.ts index fe42c6952bd..89097eeac26 100644 --- a/gateway/src/log-redact.ts +++ b/gateway/src/log-redact.ts @@ -86,12 +86,50 @@ function redactValue(value: unknown, depth: number): unknown { return value; } +// --------------------------------------------------------------------------- +// Error serialization — extracts non-enumerable Error fields and cause chain +// --------------------------------------------------------------------------- + +function serializeError(err: unknown, depth: number): unknown { + if (depth > 8 || err == null) return err; + + if (!(err instanceof Error)) { + return err; + } + + const serialized: Record = { + name: err.name, + message: err.message, + }; + + if ("code" in err && typeof (err as { code: unknown }).code === "string") { + serialized.code = (err as { code: string }).code; + } + + if (err.stack) { + serialized.stack = err.stack; + } + + if (err.cause !== undefined) { + serialized.cause = serializeError(err.cause, depth + 1); + } + + // Preserve any additional enumerable properties + for (const [key, val] of Object.entries(err)) { + if (!(key in serialized)) { + serialized[key] = val; + } + } + + return serialized; +} + // --------------------------------------------------------------------------- // Pino serializers // --------------------------------------------------------------------------- export const logSerializers: Record unknown> = { - err: (err) => redactValue(err, 0), + err: (err) => redactValue(serializeError(err, 0), 0), req: (req) => redactValue(req, 0), res: (res) => redactValue(res, 0), };