refactor(core): preserve original error as cause on DuplicateExecutionError

This commit is contained in:
Michael Siega
2026-04-18 18:42:51 +02:00
parent 1ea72cea5e
commit da9a96b0ec
4 changed files with 11 additions and 5 deletions

View File

@@ -1,7 +1,12 @@
import { OperationalError } from 'n8n-workflow';
export class DuplicateExecutionError extends OperationalError {
constructor(readonly deduplicationKey: string) {
super(`Execution with deduplication key "${deduplicationKey}" already exists`);
constructor(
readonly deduplicationKey: string,
cause?: Error,
) {
super(`Execution with deduplication key "${deduplicationKey}" already exists`, {
cause,
});
}
}

View File

@@ -185,6 +185,7 @@ describe('ExecutionPersistence', () => {
);
await expect(executionPersistence.create(payloadWithKey)).rejects.toMatchObject({
deduplicationKey: 'wf-1:node-1:1700000000000',
cause: uniqueViolation,
});
});

View File

@@ -68,7 +68,7 @@ export class ExecutionPersistence {
});
} catch (error) {
if (executionEntity.deduplicationKey && isUniqueViolationError(error)) {
throw new DuplicateExecutionError(executionEntity.deduplicationKey);
throw new DuplicateExecutionError(executionEntity.deduplicationKey, error as Error);
}
throw error;
}

View File

@@ -8,6 +8,6 @@ const UNIQUE_VIOLATION_CODES = new Set([
export function isUniqueViolationError(error: unknown): boolean {
if (!(error instanceof QueryFailedError)) return false;
const driverError = (error as unknown as { driverError?: { code?: string } }).driverError;
return typeof driverError?.code === 'string' && UNIQUE_VIOLATION_CODES.has(driverError.code);
const code = (error.driverError as { code?: unknown })?.code;
return typeof code === 'string' && UNIQUE_VIOLATION_CODES.has(code);
}