refactor(core): Reorganize error hierarchy in core and workflow packages (no-changelog) (#7820)

Ensure all errors in `core` and `workflow` inherit from
`ApplicationError` so that we start normalizing all the errors we report
to Sentry

Follow-up to:
https://github.com/n8n-io/n8n/pull/7757#discussion_r1404338844

### `core` package

`ApplicationError`
- `FileSystemError` (abstract)
	- `FileNotFoundError`
	- `DisallowedFilepathError`
- `BinaryDataError` (abstract)
	- `InvalidModeError`
	- `InvalidManagerError`
- `InvalidExecutionMetadataError`

### `workflow` package

`ApplicationError`
- `ExecutionBaseError` (abstract)
	- `WorkflowActivationError`
		- `WorkflowDeactivationError`
		- `WebhookTakenError`
	- `WorkflowOperationError`
		- `SubworkflowOperationError`
			- `CliWorkflowOperationError`
	- `ExpressionError`
		- `ExpressionExtensionError`
	- `NodeError` (abstract)
		- `NodeOperationError`
		- `NodeApiError`
	- `NodeSSLError`

Up next:
- Reorganize errors in `cli`
- Flatten the hierarchy in `workflow` (do we really need
`ExecutionBaseError`?)
- Remove `ExecutionError` type
- Stop throwing plain `Error`s
- Replace `severity` with `level`
- Add node and credential types as `tags`
- Add workflow IDs and execution IDs as `extras`
This commit is contained in:
Iván Ovejero
2023-11-27 15:33:21 +01:00
committed by GitHub
parent aae45b043b
commit dff8456382
53 changed files with 758 additions and 694 deletions

View File

@@ -6,7 +6,7 @@ import { setMaxListeners } from 'events';
import PCancelable from 'p-cancelable';
import type {
ExecutionError,
ExecutionBaseError,
ExecutionStatus,
GenericValue,
IConnection,
@@ -797,7 +797,7 @@ export class WorkflowExecute {
// Variables which hold temporary data for each node-execution
let executionData: IExecuteData;
let executionError: ExecutionError | undefined;
let executionError: ExecutionBaseError | undefined;
let executionNode: INode;
let nodeSuccessData: INodeExecutionData[][] | null | undefined;
let runIndex: number;
@@ -838,11 +838,13 @@ export class WorkflowExecute {
await this.executeHook('workflowExecuteBefore', [workflow]);
}
} catch (error) {
const e = error as unknown as ExecutionBaseError;
// Set the error that it can be saved correctly
executionError = {
...(error as NodeOperationError | NodeApiError),
message: (error as NodeOperationError | NodeApiError).message,
stack: (error as NodeOperationError | NodeApiError).stack,
...e,
message: e.message,
stack: e.stack,
};
// Set the incoming data of the node that it can be saved correctly
@@ -1253,10 +1255,12 @@ export class WorkflowExecute {
} catch (error) {
this.runExecutionData.resultData.lastNodeExecuted = executionData.node.name;
const e = error as unknown as ExecutionBaseError;
executionError = {
...(error as NodeOperationError | NodeApiError),
message: (error as NodeOperationError | NodeApiError).message,
stack: (error as NodeOperationError | NodeApiError).stack,
...e,
message: e.message,
stack: e.stack,
};
Logger.debug(`Running node "${executionNode.name}" finished with error`, {
@@ -1325,11 +1329,17 @@ export class WorkflowExecute {
lineResult.json.$error !== undefined &&
lineResult.json.$json !== undefined
) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
lineResult.error = lineResult.json.$error as NodeApiError | NodeOperationError;
lineResult.json = {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
error: (lineResult.json.$error as NodeApiError | NodeOperationError).message,
};
} else if (lineResult.error !== undefined) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
lineResult.json = { error: lineResult.error.message };
}
}
@@ -1697,7 +1707,7 @@ export class WorkflowExecute {
async processSuccessExecution(
startedAt: Date,
workflow: Workflow,
executionError?: ExecutionError,
executionError?: ExecutionBaseError,
closeFunction?: Promise<void>,
): Promise<IRun> {
const fullRunData = this.getFullRunData(startedAt);
@@ -1711,7 +1721,7 @@ export class WorkflowExecute {
...executionError,
message: executionError.message,
stack: executionError.stack,
} as ExecutionError;
} as ExecutionBaseError;
if (executionError.message?.includes('canceled')) {
fullRunData.status = 'canceled';
}