From afb15a8584cd4dbee4969843b367aaf430353d3e Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 10 Mar 2026 11:05:01 -0700 Subject: [PATCH] Improve error display in logs viewer: show message and stack trace Errors from JSONL files are serialized as plain objects with message/stack properties, not Error instances. The summary line now displays the error message correctly, and the expandable detail panel shows the full stack trace in a monospace preformatted block for easier debugging. --- packages/spike/src/server/logs.tsx | 35 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/spike/src/server/logs.tsx b/packages/spike/src/server/logs.tsx index c464524..86af6f2 100644 --- a/packages/spike/src/server/logs.tsx +++ b/packages/spike/src/server/logs.tsx @@ -19,11 +19,28 @@ const typeColors: Record = { const summaryFields = ["type", "ts"] as const +function errorMessage(error: unknown): string { + if (error instanceof Error) return error.message + if (typeof error === "object" && error && "message" in error) return String((error as any).message) + return String(error) +} + +function errorStack(error: unknown): string | undefined { + if (error instanceof Error) return error.stack + if (typeof error === "object" && error && "stack" in error) return String((error as any).stack) +} + function getEventMeta(event: StoredLogEvent): Record { const meta: Record = {} for (const [key, value] of Object.entries(event)) { if (summaryFields.includes(key as any)) continue if (value === undefined) continue + if (key === "error") { + meta[key] = errorMessage(value) + const stack = errorStack(value) + if (stack) meta.stack = stack + continue + } meta[key] = typeof value === "string" ? value : String(value) } return meta @@ -43,8 +60,7 @@ function EventRow({ event, index }: { event: StoredLogEvent; index: number }) { if ("eventType" in event) details.push(event.eventType) if (event.type === "error" && event.context) details.push(event.context) if (event.type === "error") { - const msg = event.error instanceof Error ? event.error.message : String(event.error) - details.push(msg) + details.push(errorMessage(event.error)) } const meta = getEventMeta(event) @@ -72,10 +88,17 @@ function EventRow({ event, index }: { event: StoredLogEvent; index: number }) {
{Object.entries(meta).map(([key, value]) => ( -
- {key} - {value} -
+ key === "stack" ? ( +
+ {key} +
{value}
+
+ ) : ( +
+ {key} + {value} +
+ ) ))}