diff --git a/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts b/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts index d6f65e2cfa..9635e7eae6 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts @@ -758,17 +758,20 @@ describe('JsTaskRunner', () => { await runner.receivedSettings(taskId, task.settings); - expect(sendSpy).toHaveBeenCalledWith( - JSON.stringify({ - type: 'runner:taskerror', - taskId, - error: { - message: 'unknown is not defined [line 1]', - description: 'ReferenceError', - lineNumber: 1, - }, - }), - ); - }, 1000); + expect(sendSpy).toHaveBeenCalled(); + const calledWith = sendSpy.mock.calls[0][0] as string; + expect(typeof calledWith).toBe('string'); + const calledObject = JSON.parse(calledWith); + expect(calledObject).toEqual({ + type: 'runner:taskerror', + taskId, + error: { + stack: expect.any(String), + message: 'unknown is not defined [line 1]', + description: 'ReferenceError', + lineNumber: 1, + }, + }); + }); }); }); diff --git a/packages/@n8n/task-runner/src/js-task-runner/errors/__tests__/execution-error.test.ts b/packages/@n8n/task-runner/src/js-task-runner/errors/__tests__/execution-error.test.ts index 3777940021..c85e52f977 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/errors/__tests__/execution-error.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/errors/__tests__/execution-error.test.ts @@ -42,6 +42,7 @@ describe('ExecutionError', () => { expect(JSON.stringify(executionError)).toBe( JSON.stringify({ + stack: defaultStack, message: 'a.unknown is not a function [line 2, for item 1]', description: 'TypeError', itemIndex: 1, diff --git a/packages/@n8n/task-runner/src/js-task-runner/errors/serializable-error.ts b/packages/@n8n/task-runner/src/js-task-runner/errors/serializable-error.ts index cd0e568de0..ea6321746b 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/errors/serializable-error.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/errors/serializable-error.ts @@ -1,3 +1,24 @@ +/** + * Makes the given error's `message` and `stack` properties enumerable + * so they can be serialized with JSON.stringify + */ +export function makeSerializable(error: Error) { + Object.defineProperties(error, { + message: { + value: error.message, + enumerable: true, + configurable: true, + }, + stack: { + value: error.stack, + enumerable: true, + configurable: true, + }, + }); + + return error; +} + /** * Error that has its message property serialized as well. Used to transport * errors over the wire. @@ -6,16 +27,6 @@ export abstract class SerializableError extends Error { constructor(message: string) { super(message); - // So it is serialized as well - this.makeMessageEnumerable(); - } - - private makeMessageEnumerable() { - Object.defineProperty(this, 'message', { - value: this.message, - enumerable: true, // This makes the message property enumerable - writable: true, - configurable: true, - }); + makeSerializable(this); } } diff --git a/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts b/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts index 4a7235f5d1..cf53ba425c 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts @@ -27,6 +27,7 @@ import { type Task, TaskRunner } from '@/task-runner'; import { isErrorLike } from './errors/error-like'; import { ExecutionError } from './errors/execution-error'; +import { makeSerializable } from './errors/serializable-error'; import type { RequireResolver } from './require-resolver'; import { createRequireResolver } from './require-resolver'; import { validateRunForAllItemsOutput, validateRunForEachItemOutput } from './result-validation'; @@ -323,7 +324,7 @@ export class JsTaskRunner extends TaskRunner { private toExecutionErrorIfNeeded(error: unknown): Error { if (error instanceof Error) { - return error; + return makeSerializable(error); } if (isErrorLike(error)) { diff --git a/packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts b/packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts index 8f6fa40719..dfd000b6d3 100644 --- a/packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts +++ b/packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts @@ -21,10 +21,6 @@ export class WrappedExecutionError extends ApplicationError { private copyErrorProperties(error: WrappableError) { for (const key of Object.getOwnPropertyNames(error)) { - if (key === 'message' || key === 'stack') { - continue; - } - this[key] = error[key]; } }