diff --git a/packages/cli/src/UserManagement/PermissionChecker.ts b/packages/cli/src/UserManagement/PermissionChecker.ts index de1e60f610..75e2deb2cd 100644 --- a/packages/cli/src/UserManagement/PermissionChecker.ts +++ b/packages/cli/src/UserManagement/PermissionChecker.ts @@ -1,6 +1,6 @@ import { Service } from 'typedi'; import type { INode, Workflow } from 'n8n-workflow'; -import { NodeOperationError, WorkflowOperationError } from 'n8n-workflow'; +import { CredentialAccessError, NodeOperationError, WorkflowOperationError } from 'n8n-workflow'; import config from '@/config'; import { License } from '@/License'; @@ -59,13 +59,10 @@ export class PermissionChecker { if (inaccessibleCredIds.length === 0) return; // if disallowed, flag only first node using first inaccessible cred + const inaccessibleCredId = inaccessibleCredIds[0]; + const nodeToFlag = credIdsToNodes[inaccessibleCredId][0]; - const nodeToFlag = credIdsToNodes[inaccessibleCredIds[0]][0]; - - throw new NodeOperationError(nodeToFlag, 'Node has no access to credential', { - description: 'Please recreate the credential or ask its owner to share it with you.', - level: 'warning', - }); + throw new CredentialAccessError(nodeToFlag, inaccessibleCredId, workflow); } async checkSubworkflowExecutePolicy( diff --git a/packages/workflow/src/errors/abstract/execution-base.error.ts b/packages/workflow/src/errors/abstract/execution-base.error.ts index 2e8bb265cb..c29e84ef87 100644 --- a/packages/workflow/src/errors/abstract/execution-base.error.ts +++ b/packages/workflow/src/errors/abstract/execution-base.error.ts @@ -1,7 +1,7 @@ import type { Functionality, IDataObject, JsonObject } from '../../Interfaces'; -import { ApplicationError } from '../application.error'; +import { ApplicationError, type ReportingOptions } from '../application.error'; -interface ExecutionBaseErrorOptions { +interface ExecutionBaseErrorOptions extends ReportingOptions { cause?: Error; errorResponse?: JsonObject; } @@ -21,13 +21,13 @@ export abstract class ExecutionBaseError extends ApplicationError { functionality: Functionality = 'regular'; - constructor(message: string, { cause, errorResponse }: ExecutionBaseErrorOptions = {}) { - const options = cause instanceof Error ? { cause } : {}; + constructor(message: string, options: ExecutionBaseErrorOptions = {}) { super(message, options); this.name = this.constructor.name; this.timestamp = Date.now(); + const { cause, errorResponse } = options; if (cause instanceof ExecutionBaseError) { this.context = cause.context; } else if (cause && !(cause instanceof Error)) { diff --git a/packages/workflow/src/errors/credential-access-error.ts b/packages/workflow/src/errors/credential-access-error.ts new file mode 100644 index 0000000000..b7ecbc3f7a --- /dev/null +++ b/packages/workflow/src/errors/credential-access-error.ts @@ -0,0 +1,26 @@ +import type { INode } from '@/Interfaces'; +import { ExecutionBaseError } from './abstract/execution-base.error'; + +export class CredentialAccessError extends ExecutionBaseError { + override readonly description = + 'Please recreate the credential or ask its owner to share it with you.'; + + override readonly level = 'warning'; + + constructor( + readonly node: INode, + credentialId: string, + workflow: { id: string; name?: string }, + ) { + super('Node has no access to credential', { + tags: { + nodeType: node.type, + }, + extra: { + workflowId: workflow.id, + workflowName: workflow.name ?? '', + credentialId, + }, + }); + } +} diff --git a/packages/workflow/src/errors/index.ts b/packages/workflow/src/errors/index.ts index 8cf0b8de0c..f24e420b49 100644 --- a/packages/workflow/src/errors/index.ts +++ b/packages/workflow/src/errors/index.ts @@ -1,5 +1,6 @@ export { ApplicationError } from './application.error'; export { ExpressionError } from './expression.error'; +export { CredentialAccessError } from './credential-access-error'; export { NodeApiError } from './node-api.error'; export { NodeOperationError } from './node-operation.error'; export { NodeSslError } from './node-ssl.error';