diff --git a/packages/core/src/errors/__tests__/error-reporter.test.ts b/packages/core/src/errors/__tests__/error-reporter.test.ts index d2369f59a49..f882922b7c2 100644 --- a/packages/core/src/errors/__tests__/error-reporter.test.ts +++ b/packages/core/src/errors/__tests__/error-reporter.test.ts @@ -2,7 +2,8 @@ import type { Logger } from '@n8n/backend-common'; import { QueryFailedError } from '@n8n/typeorm'; import type { ErrorEvent } from '@sentry/core'; import { AxiosError } from 'axios'; -import { ApplicationError, BaseError } from 'n8n-workflow'; +import { ApplicationError, BaseError, ExpressionError, NodeOperationError } from 'n8n-workflow'; +import type { INode } from 'n8n-workflow'; import type { Mock } from 'vitest'; import { mock } from 'vitest-mock-extended'; @@ -249,6 +250,32 @@ describe('ErrorReporter', () => { }); }); }); + + // `ExecutionBaseError` (the base of NodeApiError/NodeOperationError/ExpressionError) + // extends `BaseError`, so these errors are classified by the BaseError branch. + // Reporting must still be driven by their level, as before the re-parenting. + describe('ExecutionBaseError subclasses', () => { + const node = mock(); + + it('should drop warning-level node errors', async () => { + const originalException = new NodeOperationError(node, 'boom'); + + expect(originalException.level).toBe('warning'); + expect(await errorReporter.beforeSend(event, { originalException })).toEqual(null); + }); + + it('should keep error-level node errors', async () => { + const originalException = new NodeOperationError(node, 'boom', { level: 'error' }); + + expect(await errorReporter.beforeSend(event, { originalException })).toEqual(event); + }); + + it('should drop an ExpressionError', async () => { + const originalException = new ExpressionError('bad expression'); + + expect(await errorReporter.beforeSend(event, { originalException })).toEqual(null); + }); + }); }); describe('getEventLoopBlockIntegration', () => { diff --git a/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts b/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts index ab3139454d4..f481ce898cc 100644 --- a/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts +++ b/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts @@ -9,7 +9,7 @@ import type { INodeType, } from 'n8n-workflow'; import { - ApplicationError, + BaseError, NodeConnectionTypes, UnexpectedError, createRunExecutionData, @@ -254,7 +254,7 @@ describe('processRunExecutionData', () => { // eslint-disable-next-line @typescript-eslint/promise-function-async const execution = () => workflowExecute.processRunExecutionData(workflow); - expect(execution).toThrow(ApplicationError); + expect(execution).toThrow(BaseError); expect(execution).toThrow( /^The 'node' node has issues:\n- Parameter "Required Text" is required\.$/, ); diff --git a/packages/nodes-base/nodes/Aws/Cognito/test/listSearch/listSearch.test.ts b/packages/nodes-base/nodes/Aws/Cognito/test/listSearch/listSearch.test.ts index 5e15206620c..60fec277da2 100644 --- a/packages/nodes-base/nodes/Aws/Cognito/test/listSearch/listSearch.test.ts +++ b/packages/nodes-base/nodes/Aws/Cognito/test/listSearch/listSearch.test.ts @@ -1,5 +1,5 @@ import { - ApplicationError, + NodeOperationError, type ILoadOptionsFunctions, type INodeListSearchResult, } from 'n8n-workflow'; @@ -138,7 +138,7 @@ describe('AWS Cognito Functions', () => { getNode: vi.fn(), } as unknown as ILoadOptionsFunctions; - await expect(searchGroups.call(mockContext)).rejects.toThrow(ApplicationError); + await expect(searchGroups.call(mockContext)).rejects.toThrow(NodeOperationError); }); }); diff --git a/packages/workflow/src/errors/abstract/execution-base.error.ts b/packages/workflow/src/errors/abstract/execution-base.error.ts index 93f86cbd03a..74b9b8a0360 100644 --- a/packages/workflow/src/errors/abstract/execution-base.error.ts +++ b/packages/workflow/src/errors/abstract/execution-base.error.ts @@ -1,14 +1,16 @@ -import { ApplicationError, type ReportingOptions } from '@n8n/errors'; - +import { BaseError, type BaseErrorOptions } from '../base/base.error'; import type { Functionality, IDataObject, JsonObject } from '../../interfaces'; -interface ExecutionBaseErrorOptions extends ReportingOptions { +interface ExecutionBaseErrorOptions extends BaseErrorOptions { cause?: Error; errorResponse?: JsonObject; } -export abstract class ExecutionBaseError extends ApplicationError { - description: string | null | undefined; +export abstract class ExecutionBaseError extends BaseError { + // `BaseError.description` is readonly, but subclasses (e.g. NodeApiError, + // ExpressionError) reassign it, so redeclare it as writable here. `declare` + // avoids re-initializing the field and clobbering the value set by `super`. + declare description: string | null | undefined; override cause?: Error;