Skip to content

Commit ae1bbf3

Browse files
authored
Omit AccessDenied and InvalidClientTokenId errors from private schema faults (#400)
1 parent e8811a3 commit ae1bbf3

File tree

4 files changed

+38
-2
lines changed

4 files changed

+38
-2
lines changed

src/schema/GetSchemaTask.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ export class GetPrivateSchemasTask extends GetSchemaTask {
9999
this.logger.info(`${schemas.length} private schemas retrieved`);
100100
} catch (error) {
101101
const { category, httpStatus } = classifyAwsError(error);
102+
103+
if (category === 'permissions' || category === 'credentials') {
104+
this.logger.info(`Skipping private schemas due to ${category} issue`);
105+
return;
106+
}
107+
102108
this.telemetry.count('getSchemas.error', 1, {
103109
attributes: { category, httpStatus },
104110
});

src/utils/AwsErrorMapper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export function classifyAwsError(error: unknown): { category: AwsErrorCategory;
7575
if (isNetworkError(error)) {
7676
return { category: 'network', httpStatus };
7777
}
78-
if (error.name === 'AccessDeniedException' || httpStatus === 403) {
78+
if (error.name === 'AccessDeniedException' || error.name === 'AccessDenied' || httpStatus === 403) {
7979
return { category: 'permissions', httpStatus };
8080
}
8181
if (error.name === 'ThrottlingException' || httpStatus === 429) {

tst/unit/schema/GetSchemaTask.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,21 @@ describe('GetSchemaTask', () => {
128128

129129
await expect(task.run(mockDataStore)).rejects.toThrow('Schema retrieval failed');
130130
});
131+
132+
it('should handle permission errors gracefully without throwing', async () => {
133+
const error = { name: 'AccessDenied', $metadata: { httpStatusCode: 403 } };
134+
const mockGetSchemas = vi.fn().mockRejectedValue(error);
135+
const task = new GetPrivateSchemasTask(mockGetSchemas);
136+
137+
await expect(task.run(mockDataStore)).resolves.not.toThrow();
138+
});
139+
140+
it('should handle credential errors gracefully without throwing', async () => {
141+
const error = { name: 'InvalidClientTokenId', $metadata: { httpStatusCode: 403 } };
142+
const mockGetSchemas = vi.fn().mockRejectedValue(error);
143+
const task = new GetPrivateSchemasTask(mockGetSchemas);
144+
145+
await expect(task.run(mockDataStore)).resolves.not.toThrow();
146+
});
131147
});
132148
});

tst/unit/utils/AwsErrorMapper.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect } from 'vitest';
22
import { ErrorCodes, ResponseError } from 'vscode-languageserver';
3-
import { mapAwsErrorToLspError } from '../../../src/utils/AwsErrorMapper';
3+
import { classifyAwsError, mapAwsErrorToLspError } from '../../../src/utils/AwsErrorMapper';
44
import { OnlineFeatureErrorCode } from '../../../src/utils/OnlineFeatureError';
55

66
describe('mapAwsErrorToLspError', () => {
@@ -69,3 +69,17 @@ describe('mapAwsErrorToLspError', () => {
6969
expect(result.message).toContain('Unknown error');
7070
});
7171
});
72+
73+
describe('classifyAwsError', () => {
74+
it('should classify AccessDenied as permissions', () => {
75+
const error = { name: 'AccessDenied', $metadata: { httpStatusCode: 403 } };
76+
const result = classifyAwsError(error);
77+
expect(result.category).toBe('permissions');
78+
});
79+
80+
it('should classify AccessDeniedException as permissions', () => {
81+
const error = { name: 'AccessDeniedException', $metadata: { httpStatusCode: 403 } };
82+
const result = classifyAwsError(error);
83+
expect(result.category).toBe('permissions');
84+
});
85+
});

0 commit comments

Comments
 (0)