From e16f8934bb75388f61711a38ba7219d62551e84d Mon Sep 17 00:00:00 2001 From: omkardongre <44136758+omkardongre@users.noreply.github.com> Date: Wed, 27 Aug 2025 01:07:17 +0530 Subject: [PATCH] Fix excessive framework noise in error stack traces Add AsyncLocalStorage to LINES_TO_IGNORE (removes OpenTelemetry noise) Apply error stack trace filtering for createJsonErrorObject Add test for framework stack trace filtering Add changeset This change improves readability of error traces in user-facing contexts (Slack alerts, email notifications, API responses, run streams) by filtering out internal framework noise that clutters error messages. --- .changeset/dry-taxis-wash.md | 5 ++++ packages/core/src/v3/errors.ts | 5 +++- packages/core/test/errors.test.ts | 48 +++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 .changeset/dry-taxis-wash.md create mode 100644 packages/core/test/errors.test.ts diff --git a/.changeset/dry-taxis-wash.md b/.changeset/dry-taxis-wash.md new file mode 100644 index 0000000000..d9a66cd46b --- /dev/null +++ b/.changeset/dry-taxis-wash.md @@ -0,0 +1,5 @@ +--- +"@trigger.dev/core": patch +--- + +Improve user-facing error readability by filtering framework noise from stack traces diff --git a/packages/core/src/v3/errors.ts b/packages/core/src/v3/errors.ts index 6cf900d7b9..1ba5802b10 100644 --- a/packages/core/src/v3/errors.ts +++ b/packages/core/src/v3/errors.ts @@ -227,7 +227,9 @@ export function createJsonErrorObject(error: TaskRunError): SerializedError { return { name: enhancedError.name, message: enhancedError.message, - stackTrace: enhancedError.stackTrace, + stackTrace: correctErrorStackTrace(enhancedError.stackTrace, undefined, { + removeFirstLine: false, + }), }; } case "STRING_ERROR": { @@ -400,6 +402,7 @@ const LINES_TO_IGNORE = [ /ZodIpc/, /startActiveSpan/, /processTicksAndRejections/, + /AsyncLocalStorage/, ]; function correctStackTraceLine(line: string, projectDir?: string, isDev?: boolean) { diff --git a/packages/core/test/errors.test.ts b/packages/core/test/errors.test.ts new file mode 100644 index 0000000000..6447533490 --- /dev/null +++ b/packages/core/test/errors.test.ts @@ -0,0 +1,48 @@ +import { createJsonErrorObject } from "../src/v3/errors.js"; +import type { TaskRunError } from "../src/v3/schemas/common.js"; + +describe("createJsonErrorObject", () => { + it("should filter internal framework noise from error stack traces", () => { + const taskRunError: TaskRunError = { + type: "BUILT_IN_ERROR", + name: "Error", + message: "Network error occurred", + stackTrace: `Error: Network error occurred + at fetchData (file:///src/trigger/utils/helper.ts:4:9) + at processResponse (file:///src/trigger/utils/helper.ts:9:10) + at parseResult (file:///src/trigger/utils/helper.ts:14:10) + at callAPI (file:///src/trigger/services/api.ts:6:10) + at localHelper (file:///src/trigger/example.ts:7:10) + at run (file:///src/trigger/example.ts:17:12) + at _tracer.startActiveSpan.attributes (file:///.npm/_npx/f51a09bd0abf5f10/node_modules/@trigger.dev/core/src/v3/workers/taskExecutor.ts:445:38) + at file:///.npm/_npx/f51a09bd0abf5f10/node_modules/@trigger.dev/core/src/v3/tracer.ts:137:24 + at AsyncLocalStorage.run (node:async_hooks:346:14) + at AsyncLocalStorageContextManager.with (file:///.npm/_npx/f51a09bd0abf5f10/node_modules/@opentelemetry/context-async-hooks/src/AsyncLocalStorageContextManager.ts:40:36)`, + }; + + const jsonError = createJsonErrorObject(taskRunError); + + // Should preserve user stack traces + expect(jsonError.stackTrace).toContain( + "at fetchData (file:///src/trigger/utils/helper.ts:4:9)" + ); + expect(jsonError.stackTrace).toContain( + "at processResponse (file:///src/trigger/utils/helper.ts:9:10)" + ); + expect(jsonError.stackTrace).toContain( + "at parseResult (file:///src/trigger/utils/helper.ts:14:10)" + ); + expect(jsonError.stackTrace).toContain("at callAPI (file:///src/trigger/services/api.ts:6:10)"); + expect(jsonError.stackTrace).toContain("at localHelper (file:///src/trigger/example.ts:7:10)"); + expect(jsonError.stackTrace).toContain("at run (file:///src/trigger/example.ts:17:12)"); + + // Should filter framework noise + expect(jsonError.stackTrace).not.toContain("_tracer.startActiveSpan.attributes"); + expect(jsonError.stackTrace).not.toContain("taskExecutor.ts"); + expect(jsonError.stackTrace).not.toContain("tracer.ts"); + expect(jsonError.stackTrace).not.toContain("AsyncLocalStorage.run"); + expect(jsonError.stackTrace).not.toContain("AsyncLocalStorageContextManager"); + expect(jsonError.stackTrace).not.toContain("node_modules/@trigger.dev/core"); + expect(jsonError.stackTrace).not.toContain(".npm/_npx"); + }); +});