refactor: Replace deprecated ApplicationError in credentials (no-changelog) (#32230)

Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
This commit is contained in:
Tomi Turtiainen
2026-06-12 16:55:00 +03:00
committed by GitHub
parent 607634ad27
commit 973417bbc3
9 changed files with 38 additions and 44 deletions
@@ -4,7 +4,7 @@ import type {
IHttpRequestOptions,
INodeProperties,
} from 'n8n-workflow';
import { ApplicationError } from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
import { type AwsAssumeRoleCredentialsType, type AWSRegion } from './common/aws/types';
import { awsCustomEndpoints, awsRegionProperty } from './common/aws/descriptions';
@@ -142,7 +142,7 @@ export class AwsAssumeRole implements ICredentialType {
finalCredentials = { ...credentials, ...securityHeaders };
} catch (error) {
console.error('Failed to assume role:', error);
throw new ApplicationError(
throw new UserError(
`Failed to assume role: ${error instanceof Error ? error.message : 'Unknown error'}`,
);
}
@@ -1,10 +1,10 @@
import { ApplicationError } from '@n8n/errors';
import type {
ICredentialDataDecryptedObject,
ICredentialType,
IHttpRequestOptions,
INodeProperties,
} from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
export class CustomerIoApi implements ICredentialType {
name = 'customerIoApi';
@@ -91,7 +91,7 @@ export class CustomerIoApi implements ICredentialType {
Authorization: `Bearer ${credentials.appApiKey as string}`,
});
} else {
throw new ApplicationError('Unknown way of authenticating', { level: 'warning' });
throw new UserError('Unknown way of authenticating', { level: 'warning' });
}
return requestOptions;
@@ -1,4 +1,3 @@
import { ApplicationError } from '@n8n/errors';
import type {
IAuthenticateGeneric,
ICredentialDataDecryptedObject,
@@ -8,6 +7,7 @@ import type {
INodeProperties,
Icon,
} from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
export class ZscalerZiaApi implements ICredentialType {
name = 'zscalerZiaApi';
@@ -122,7 +122,7 @@ export class ZscalerZiaApi implements ICredentialType {
?.find((entry) => entry.includes('JSESSIONID'));
if (!cookie) {
throw new ApplicationError('No cookie returned. Please check your credentials.', {
throw new UserError('No cookie returned. Please check your credentials.', {
level: 'warning',
});
}
@@ -1,4 +1,4 @@
import { ApplicationError } from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
global.fetch = jest.fn();
@@ -60,10 +60,10 @@ describe('system-credentials-utils', () => {
});
describe('getSystemCredentials', () => {
it('should throw ApplicationError when AWS system credentials access is disabled', async () => {
it('should throw UserError when AWS system credentials access is disabled', async () => {
mockSecurityConfigInstance.awsSystemCredentialsAccess = false;
await expect(getSystemCredentials()).rejects.toThrow(ApplicationError);
await expect(getSystemCredentials()).rejects.toThrow(UserError);
await expect(getSystemCredentials()).rejects.toThrow(
'Access to AWS system credentials disabled, contact your administrator.',
);
@@ -1,6 +1,6 @@
import { SecurityConfig } from '@n8n/config';
import { Container } from '@n8n/di';
import { ApplicationError } from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
import { readFile } from 'fs/promises';
type Resolvers =
@@ -36,9 +36,7 @@ export const credentialsResolver: Record<Resolvers, () => Promise<ReturnData | n
*/
export async function getSystemCredentials() {
if (!Container.get(SecurityConfig).awsSystemCredentialsAccess) {
throw new ApplicationError(
'Access to AWS system credentials disabled, contact your administrator.',
);
throw new UserError('Access to AWS system credentials disabled, contact your administrator.');
}
const resolveOrder: Resolvers[] = [
@@ -1,4 +1,4 @@
import { ApplicationError } from 'n8n-workflow';
import { OperationalError, UserError } from 'n8n-workflow';
import type { AwsAssumeRoleCredentialsType, AwsIamCredentialsType, AWSRegion } from './types';
global.fetch = jest.fn();
@@ -203,7 +203,7 @@ describe('assumeRole', () => {
jest.spyOn(systemCredentialsUtils, 'getSystemCredentials').mockResolvedValue(null);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(UserError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'System AWS credentials are required for role assumption',
);
@@ -371,7 +371,7 @@ describe('assumeRole', () => {
stsSecretAccessKey: 'sts-secret-key',
};
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(UserError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'STS Access Key ID is required when not using system credentials',
);
@@ -389,7 +389,7 @@ describe('assumeRole', () => {
stsSecretAccessKey: 'sts-secret-key',
};
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(UserError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'STS Access Key ID is required when not using system credentials',
);
@@ -406,7 +406,7 @@ describe('assumeRole', () => {
stsAccessKeyId: 'sts-access-key',
};
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(UserError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'STS Secret Access Key is required when not using system credentials',
);
@@ -424,7 +424,7 @@ describe('assumeRole', () => {
stsSecretAccessKey: ' ',
};
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(UserError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'STS Secret Access Key is required when not using system credentials',
);
@@ -575,7 +575,7 @@ describe('assumeRole', () => {
throw new Error('Signing failed');
});
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(OperationalError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'Failed to sign STS request',
);
@@ -602,7 +602,7 @@ describe('assumeRole', () => {
mockFetch.mockResolvedValue(mockResponse as any);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(UserError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'STS AssumeRole failed: 403 Forbidden - Access denied',
);
@@ -661,7 +661,7 @@ describe('assumeRole', () => {
});
});
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(OperationalError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'Invalid response from STS AssumeRole',
);
@@ -692,7 +692,7 @@ describe('assumeRole', () => {
});
});
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(OperationalError);
await expect(assumeRole(credentials, 'us-east-1')).rejects.toThrow(
'Invalid response from STS AssumeRole',
);
@@ -772,14 +772,14 @@ describe('assertSupportedAwsRegion', () => {
['169.254.169.254'],
['localhost'],
])('rejects unsupported region value %s', (region) => {
expect(() => assertSupportedAwsRegion(region)).toThrow(ApplicationError);
expect(() => assertSupportedAwsRegion(region)).toThrow(UserError);
expect(() => assertSupportedAwsRegion(region)).toThrow('Unsupported AWS region');
});
it.each([[undefined], [null], [0], [true], [{}], [['us-east-1']]])(
'rejects non-string region value %s',
(region) => {
expect(() => assertSupportedAwsRegion(region)).toThrow(ApplicationError);
expect(() => assertSupportedAwsRegion(region)).toThrow(UserError);
},
);
});
@@ -839,7 +839,7 @@ describe('awsGetSignInOptionsAndUpdateRequest', () => {
'lambda',
region as any,
),
).toThrow(ApplicationError);
).toThrow(UserError);
});
});
@@ -872,7 +872,7 @@ describe('assumeRole region validation', () => {
stsSecretAccessKey: 'sts-secret-key',
};
await expect(assumeRole(credentials, region as any)).rejects.toThrow(ApplicationError);
await expect(assumeRole(credentials, region as any)).rejects.toThrow(UserError);
await expect(assumeRole(credentials, region as any)).rejects.toThrow(
'Unsupported AWS region',
);
@@ -1,6 +1,5 @@
import { resolveProxyUrl } from '@n8n/backend-network';
import {
ApplicationError,
type IHttpRequestMethods,
isObjectEmpty,
sanitizeXmlName,
@@ -8,6 +7,7 @@ import {
type IDataObject,
type IHttpRequestOptions,
type IRequestOptions,
OperationalError,
UserError,
} from 'n8n-workflow';
import { parseString } from 'xml2js';
@@ -52,7 +52,7 @@ const SUPPORTED_AWS_REGIONS: ReadonlySet<string> = new Set(regions.map((r) => r.
*/
export function assertSupportedAwsRegion(region: unknown): asserts region is AWSRegion {
if (typeof region !== 'string' || !SUPPORTED_AWS_REGIONS.has(region)) {
throw new ApplicationError('Unsupported AWS region');
throw new UserError('Unsupported AWS region');
}
}
@@ -281,7 +281,7 @@ export function awsGetSignInOptionsAndUpdateRequest(
* @param credentials - The assume role credentials configuration
* @param region - AWS region for the STS endpoint
* @returns Promise resolving to temporary credentials for the assumed role
* @throws {ApplicationError} When credentials are invalid or STS call fails
* @throws {UserError | OperationalError} When credentials are invalid or STS call fails
*
* @see {@link https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html STS AssumeRole API}
*/
@@ -312,7 +312,7 @@ export async function assumeRole(
if (useSystemCredentialsForRole) {
const systemCredentials = await getSystemCredentials();
if (!systemCredentials) {
throw new ApplicationError(
throw new UserError(
'System AWS credentials are required for role assumption. Please ensure AWS credentials are available via environment variables, instance metadata, or container role.',
);
}
@@ -320,14 +320,10 @@ export async function assumeRole(
stsCallCredentials = systemCredentials;
} else {
if (!credentials.stsAccessKeyId || credentials.stsAccessKeyId.trim() === '') {
throw new ApplicationError(
'STS Access Key ID is required when not using system credentials.',
);
throw new UserError('STS Access Key ID is required when not using system credentials.');
}
if (!credentials.stsSecretAccessKey || credentials.stsSecretAccessKey.trim() === '') {
throw new ApplicationError(
'STS Secret Access Key is required when not using system credentials.',
);
throw new UserError('STS Secret Access Key is required when not using system credentials.');
}
const sessionToken = credentials.stsSessionToken?.trim() || undefined;
@@ -376,7 +372,7 @@ export async function assumeRole(
sign(signOpts, stsCallCredentials);
} catch (err) {
console.error('Failed to sign STS request:', err);
throw new ApplicationError('Failed to sign STS request');
throw new OperationalError('Failed to sign STS request');
}
const proxyUrl = resolveProxyUrl(stsEndpoint);
@@ -391,7 +387,7 @@ export async function assumeRole(
if (!response.ok) {
const errorText = await response.text();
throw new ApplicationError(
throw new UserError(
`STS AssumeRole failed: ${response.status} ${response.statusText} - ${errorText}`,
);
}
@@ -418,7 +414,7 @@ export async function assumeRole(
const assumeRoleResult = (responseData.AssumeRoleResponse as IDataObject)
?.AssumeRoleResult as IDataObject;
if (!assumeRoleResult?.Credentials) {
throw new ApplicationError('Invalid response from STS AssumeRole');
throw new OperationalError('Invalid response from STS AssumeRole');
}
const assumedCredentials = assumeRoleResult.Credentials as IDataObject;
@@ -1,6 +1,6 @@
import { mock } from 'jest-mock-extended';
import type { ICredentialTestFunctions } from 'n8n-workflow';
import { ApplicationError } from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
jest.mock('aws4', () => ({
sign: jest.fn(),
@@ -44,7 +44,7 @@ describe('AWS Textract Generic Functions', () => {
const credentials = { ...baseCredentials, region };
await expect(validateCredentials.call(context, credentials, 'textract')).rejects.toThrow(
ApplicationError,
UserError,
);
await expect(validateCredentials.call(context, credentials, 'textract')).rejects.toThrow(
'Unsupported AWS region',
@@ -1,6 +1,6 @@
import { mock } from 'jest-mock-extended';
import type { IExecuteFunctions } from 'n8n-workflow';
import { ApplicationError } from 'n8n-workflow';
import { UserError } from 'n8n-workflow';
jest.mock('aws4', () => ({
sign: jest.fn(),
@@ -57,7 +57,7 @@ describe('AWS Transcribe Generic Functions', () => {
const { context, helpers } = buildContext(region);
await expect(awsApiRequest.call(context, 'transcribe', 'POST', '/')).rejects.toThrow(
ApplicationError,
UserError,
);
await expect(awsApiRequest.call(context, 'transcribe', 'POST', '/')).rejects.toThrow(
'Unsupported AWS region',