diff --git a/packages/cli/src/ActiveWorkflowRunner.ts b/packages/cli/src/ActiveWorkflowRunner.ts index bc24be401952d..f14fb23ab95a9 100644 --- a/packages/cli/src/ActiveWorkflowRunner.ts +++ b/packages/cli/src/ActiveWorkflowRunner.ts @@ -682,6 +682,15 @@ export class ActiveWorkflowRunner { (error) => console.error(error), ); }; + returnFunctions.emitError = async (error: Error): Promise => { + await this.activeWorkflows?.remove(workflowData.id.toString()); + this.activationErrors[workflowData.id.toString()] = { + time: new Date().getTime(), + error: { + message: error.message, + }, + }; + }; return returnFunctions; }; } diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 1d54de9a114a8..02c0723438e87 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -1750,6 +1750,9 @@ export function getExecuteTriggerFunctions( emit: (data: INodeExecutionData[][]): void => { throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!'); }, + emitError: (error: Error): void => { + throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!'); + }, async getCredentials(type: string): Promise { return getCredentials(workflow, node, type, additionalData, mode); }, diff --git a/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts b/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts index 3cd39dfb9bfc0..2f1104d3e21ab 100644 --- a/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts +++ b/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts @@ -1,13 +1,15 @@ import { ITriggerFunctions } from 'n8n-core'; import { + createDeferredPromise, IBinaryData, IBinaryKeyData, IDataObject, + IDeferredPromise, INodeExecutionData, INodeType, INodeTypeDescription, ITriggerResponse, - LoggerProxy, + LoggerProxy as Logger, NodeOperationError, } from 'n8n-workflow'; @@ -25,10 +27,6 @@ import { import * as lodash from 'lodash'; -import { - LoggerProxy as Logger -} from 'n8n-workflow'; - export class EmailReadImap implements INodeType { description: INodeTypeDescription = { displayName: 'EmailReadImap', @@ -377,6 +375,8 @@ export class EmailReadImap implements INodeType { return newEmails; }; + const returnedPromise: IDeferredPromise | undefined = await createDeferredPromise(); + const establishConnection = (): Promise => { let searchCriteria = [ @@ -425,7 +425,11 @@ export class EmailReadImap implements INodeType { } } catch (error) { Logger.error('Email Read Imap node encountered an error fetching new emails', { error }); - throw error; + // Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy + // if it receives an error before the workflow got activated + returnedPromise.promise().then(() => { + this.emitError(error as Error); + }); } } }, @@ -475,10 +479,12 @@ export class EmailReadImap implements INodeType { await connection.end(); } + // Resolve returned-promise so that waiting errors can be emitted + returnedPromise.resolve(); + return { closeFunction, }; - } } diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 058b471c43375..5a0fba9d00b0e 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -683,6 +683,7 @@ export interface ITriggerFunctions { data: INodeExecutionData[][], responsePromise?: IDeferredPromise, ): void; + emitError(error: Error, responsePromise?: IDeferredPromise): void; getCredentials(type: string): Promise; getMode(): WorkflowExecuteMode; getActivationMode(): WorkflowActivateMode; diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index db696ab9fd51d..adcee421bcf37 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -949,7 +949,7 @@ export class Workflow { const triggerResponse = await nodeType.trigger.call(triggerFunctions); // Add the manual trigger response which resolves when the first time data got emitted - triggerResponse!.manualTriggerResponse = new Promise((resolve) => { + triggerResponse!.manualTriggerResponse = new Promise((resolve, reject) => { triggerFunctions.emit = ( (resolveEmit) => ( @@ -967,6 +967,20 @@ export class Workflow { resolveEmit(data); } )(resolve); + triggerFunctions.emitError = ( + (rejectEmit) => + (error: Error, responsePromise?: IDeferredPromise) => { + additionalData.hooks!.hookFunctions.sendResponse = [ + async (): Promise => { + if (responsePromise) { + responsePromise.reject(error); + } + }, + ]; + + rejectEmit(error); + } + )(reject); }); return triggerResponse;