refactor(core): Switch plain errors in core to ApplicationError (no-changelog) (#7873)

Ensure all errors in `core` are `ApplicationError` or children of it and
contain no variables in the message, to continue normalizing all the
errors we report to Sentry

Follow-up to: https://github.com/n8n-io/n8n/pull/7857
This commit is contained in:
Iván Ovejero
2023-11-30 09:06:19 +01:00
committed by GitHub
parent cd474f1562
commit b16dd21909
10 changed files with 135 additions and 101 deletions

View File

@@ -112,6 +112,7 @@ import {
validateFieldType,
ExecutionBaseError,
jsonParse,
ApplicationError,
} from 'n8n-workflow';
import type { Token } from 'oauth-1.0a';
import clientOAuth1 from 'oauth-1.0a';
@@ -1198,7 +1199,7 @@ export async function requestOAuth2(
credentials.grantType === OAuth2GrantType.authorizationCode &&
credentials.oauthTokenData === undefined
) {
throw new Error('OAuth credentials not connected!');
throw new ApplicationError('OAuth credentials not connected');
}
const oAuthClient = new ClientOAuth2({
@@ -1218,9 +1219,10 @@ export async function requestOAuth2(
const { data } = await getClientCredentialsToken(oAuthClient, credentials);
// Find the credentials
if (!node.credentials?.[credentialsType]) {
throw new Error(
`The node "${node.name}" does not have credentials of type "${credentialsType}"!`,
);
throw new ApplicationError('Node does not have credential type', {
extra: { nodeName: node.name },
tags: { credentialType: credentialsType },
});
}
const nodeCredentials = node.credentials[credentialsType];
@@ -1302,9 +1304,9 @@ export async function requestOAuth2(
credentials.oauthTokenData = newToken.data;
// Find the credentials
if (!node.credentials?.[credentialsType]) {
throw new Error(
`The node "${node.name}" does not have credentials of type "${credentialsType}"!`,
);
throw new ApplicationError('Node does not have credential type', {
extra: { nodeName: node.name, credentialType: credentialsType },
});
}
const nodeCredentials = node.credentials[credentialsType];
await additionalData.credentialsHelper.updateCredentials(
@@ -1379,9 +1381,10 @@ export async function requestOAuth2(
// Find the credentials
if (!node.credentials?.[credentialsType]) {
throw new Error(
`The node "${node.name}" does not have credentials of type "${credentialsType}"!`,
);
throw new ApplicationError('Node does not have credential type', {
tags: { credentialType: credentialsType },
extra: { nodeName: node.name },
});
}
const nodeCredentials = node.credentials[credentialsType];
@@ -1426,11 +1429,11 @@ export async function requestOAuth1(
const credentials = await this.getCredentials(credentialsType);
if (credentials === undefined) {
throw new Error('No credentials were returned!');
throw new ApplicationError('No credentials were returned!');
}
if (credentials.oauthTokenData === undefined) {
throw new Error('OAuth credentials not connected!');
throw new ApplicationError('OAuth credentials not connected!');
}
const oauth = new clientOAuth1({
@@ -1651,7 +1654,7 @@ export function normalizeItems(
return executionData;
if (executionData.some((item) => typeof item === 'object' && 'json' in item)) {
throw new Error('Inconsistent item format');
throw new ApplicationError('Inconsistent item format');
}
if (executionData.every((item) => typeof item === 'object' && 'binary' in item)) {
@@ -1671,7 +1674,7 @@ export function normalizeItems(
}
if (executionData.some((item) => typeof item === 'object' && 'binary' in item)) {
throw new Error('Inconsistent item format');
throw new ApplicationError('Inconsistent item format');
}
return executionData.map((item) => {
@@ -2229,13 +2232,15 @@ export function getNodeParameter(
): NodeParameterValueType | object {
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
if (nodeType === undefined) {
throw new Error(`Node type "${node.type}" is not known so can not return parameter value!`);
throw new ApplicationError('Node type is unknown so cannot return parameter value', {
tags: { nodeType: node.type },
});
}
const value = get(node.parameters, parameterName, fallbackValue);
if (value === undefined) {
throw new Error(`Could not get parameter "${parameterName}"!`);
throw new ApplicationError('Could not get parameter', { extra: { parameterName } });
}
if (options?.rawExpressions) {
@@ -2393,7 +2398,9 @@ const addExecutionDataFunctions = async (
currentNodeRunIndex: number,
): Promise<void> => {
if (connectionType === 'main') {
throw new Error(`Setting the ${type} is not supported for the main connection!`);
throw new ApplicationError('Setting type is not supported for main connection', {
extra: { type },
});
}
let taskData: ITaskData | undefined;
@@ -2946,7 +2953,7 @@ const getBinaryHelperFunctions = (
setBinaryDataBuffer: async (data, binaryData) =>
setBinaryDataBuffer(data, binaryData, workflowId, executionId!),
copyBinaryFile: async () => {
throw new Error('copyBinaryFile has been removed. Please upgrade this node');
throw new ApplicationError('`copyBinaryFile` has been removed. Please upgrade this node.');
},
});
@@ -2983,10 +2990,12 @@ export function getExecutePollFunctions(
return {
...getCommonWorkflowFunctions(workflow, node, additionalData),
__emit: (data: INodeExecutionData[][]): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecutePollFunctions.__emit function!');
throw new ApplicationError(
'Overwrite NodeExecuteFunctions.getExecutePollFunctions.__emit function!',
);
},
__emitError(error: Error) {
throw new Error(
throw new ApplicationError(
'Overwrite NodeExecuteFunctions.getExecutePollFunctions.__emitError function!',
);
},
@@ -3043,10 +3052,14 @@ export function getExecuteTriggerFunctions(
return {
...getCommonWorkflowFunctions(workflow, node, additionalData),
emit: (data: INodeExecutionData[][]): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!');
throw new ApplicationError(
'Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!',
);
},
emitError: (error: Error): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!');
throw new ApplicationError(
'Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!',
);
},
getMode: () => mode,
getActivationMode: () => activation,
@@ -3174,7 +3187,9 @@ export function getExecuteFunctions(
});
if (inputConfiguration === undefined) {
throw new Error(`The node "${node.name}" does not have an input of type "${inputName}"`);
throw new ApplicationError('Node does not have input of type', {
extra: { nodeName: node.name, inputName },
});
}
if (typeof inputConfiguration === 'string') {
@@ -3200,9 +3215,9 @@ export function getExecuteFunctions(
);
if (!nodeType.supplyData) {
throw new Error(
`The node "${connectedNode.name}" does not have a "supplyData" method defined!`,
);
throw new ApplicationError('Node does not have a `supplyData` method defined', {
extra: { nodeName: connectedNode.name },
});
}
const context = Object.assign({}, this);
@@ -3350,12 +3365,15 @@ export function getExecuteFunctions(
// TODO: Check if nodeType has input with that index defined
if (inputData[inputName].length < inputIndex) {
throw new Error(`Could not get input index "${inputIndex}" of input "${inputName}"!`);
throw new ApplicationError('Could not get input with given index', {
extra: { inputIndex, inputName },
});
}
if (inputData[inputName][inputIndex] === null) {
// return [];
throw new Error(`Value "${inputIndex}" of input "${inputName}" did not get set!`);
throw new ApplicationError('Value of input was not set', {
extra: { inputIndex, inputName },
});
}
return inputData[inputName][inputIndex] as INodeExecutionData[];
@@ -3363,7 +3381,7 @@ export function getExecuteFunctions(
getInputSourceData: (inputIndex = 0, inputName = 'main') => {
if (executeData?.source === null) {
// Should never happen as n8n sets it automatically
throw new Error('Source data is missing!');
throw new ApplicationError('Source data is missing');
}
return executeData.source[inputName][inputIndex];
},
@@ -3573,21 +3591,23 @@ export function getExecuteSingleFunctions(
// TODO: Check if nodeType has input with that index defined
if (inputData[inputName].length < inputIndex) {
throw new Error(`Could not get input index "${inputIndex}" of input "${inputName}"!`);
throw new ApplicationError('Could not get input index', {
extra: { inputIndex, inputName },
});
}
const allItems = inputData[inputName][inputIndex];
if (allItems === null) {
// return [];
throw new Error(`Value "${inputIndex}" of input "${inputName}" did not get set!`);
throw new ApplicationError('Input index was not set', {
extra: { inputIndex, inputName },
});
}
if (allItems[itemIndex] === null) {
// return [];
throw new Error(
`Value "${inputIndex}" of input "${inputName}" with itemIndex "${itemIndex}" did not get set!`,
);
throw new ApplicationError('Value of input with given index was not set', {
extra: { inputIndex, inputName, itemIndex },
});
}
return allItems[itemIndex];
@@ -3595,7 +3615,7 @@ export function getExecuteSingleFunctions(
getInputSourceData: (inputIndex = 0, inputName = 'main') => {
if (executeData?.source === null) {
// Should never happen as n8n sets it automatically
throw new Error('Source data is missing!');
throw new ApplicationError('Source data is missing');
}
return executeData.source[inputName][inputIndex] as ISourceData;
},
@@ -3691,9 +3711,9 @@ export function getLoadOptionsFunctions(
if (options?.extractValue) {
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
if (nodeType === undefined) {
throw new Error(
`Node type "${node.type}" is not known so can not return parameter value!`,
);
throw new ApplicationError('Node type is not known so cannot return parameter value', {
tags: { nodeType: node.type },
});
}
returnData = extractValue(
returnData,
@@ -3793,7 +3813,7 @@ export function getExecuteHookFunctions(
},
getWebhookName(): string {
if (webhookData === undefined) {
throw new Error('Is only supported in webhook functions!');
throw new ApplicationError('Only supported in webhook functions');
}
return webhookData.webhookDescription.name;
},
@@ -3818,14 +3838,14 @@ export function getExecuteWebhookFunctions(
...getCommonWorkflowFunctions(workflow, node, additionalData),
getBodyData(): IDataObject {
if (additionalData.httpRequest === undefined) {
throw new Error('Request is missing!');
throw new ApplicationError('Request is missing');
}
return additionalData.httpRequest.body;
},
getCredentials: async (type) => getCredentials(workflow, node, type, additionalData, mode),
getHeaderData(): IncomingHttpHeaders {
if (additionalData.httpRequest === undefined) {
throw new Error('Request is missing!');
throw new ApplicationError('Request is missing');
}
return additionalData.httpRequest.headers;
},
@@ -3857,25 +3877,25 @@ export function getExecuteWebhookFunctions(
},
getParamsData(): object {
if (additionalData.httpRequest === undefined) {
throw new Error('Request is missing!');
throw new ApplicationError('Request is missing');
}
return additionalData.httpRequest.params;
},
getQueryData(): object {
if (additionalData.httpRequest === undefined) {
throw new Error('Request is missing!');
throw new ApplicationError('Request is missing');
}
return additionalData.httpRequest.query;
},
getRequestObject(): Request {
if (additionalData.httpRequest === undefined) {
throw new Error('Request is missing!');
throw new ApplicationError('Request is missing');
}
return additionalData.httpRequest;
},
getResponseObject(): Response {
if (additionalData.httpResponse === undefined) {
throw new Error('Response is missing!');
throw new ApplicationError('Response is missing');
}
return additionalData.httpResponse;
},