Skip to content

Commit 90ef1af

Browse files
logaretmclaude
andcommitted
feat(feedback)!: always reject sendFeedback with an Error
Previously, sendFeedback's async rejection paths (timeout, 403, generic transport error) rejected with plain strings, while the sync-throw paths used Error instances. Unify on Error for all paths so consumers can rely on a consistent rejection shape. BREAKING CHANGE: sendFeedback now always rejects with an Error whose .message is the error code (ERROR_TIMEOUT, ERROR_FORBIDDEN, or ERROR_GENERIC). Previously these paths rejected with the raw string. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1272fb6 commit 90ef1af

3 files changed

Lines changed: 8 additions & 9 deletions

File tree

packages/feedback/src/core/sendFeedback.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { Event, EventHint, SendFeedback, SendFeedbackParams, TransportMakeRequestResponse } from '@sentry/core';
22
import { captureFeedback, getClient, getCurrentScope, getLocationHref } from '@sentry/core';
33
import { FEEDBACK_API_SOURCE } from '../constants';
4-
import type { FeedbackErrorCode } from '../util/createFeedbackError';
54
import { createFeedbackError } from '../util/createFeedbackError';
65

76
/**
@@ -39,7 +38,7 @@ export const sendFeedback: SendFeedback = (
3938
// After 30s, we want to clear anyhow
4039
const timeout = setTimeout(() => {
4140
cleanup();
42-
reject('ERROR_TIMEOUT' satisfies FeedbackErrorCode);
41+
reject(createFeedbackError('ERROR_TIMEOUT'));
4342
}, 30_000);
4443

4544
const cleanup = client.on('afterSendEvent', (event: Event, response: TransportMakeRequestResponse) => {
@@ -56,10 +55,10 @@ export const sendFeedback: SendFeedback = (
5655
}
5756

5857
if (response?.statusCode === 403) {
59-
return reject('ERROR_FORBIDDEN' satisfies FeedbackErrorCode);
58+
return reject(createFeedbackError('ERROR_FORBIDDEN'));
6059
}
6160

62-
return reject('ERROR_GENERIC' satisfies FeedbackErrorCode);
61+
return reject(createFeedbackError('ERROR_GENERIC'));
6362
});
6463
});
6564
};

packages/feedback/src/modal/components/Form.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export function Form({
145145
onSubmitSuccess(data, eventId);
146146
} catch (error) {
147147
DEBUG_BUILD && debug.error(error);
148-
const err = error instanceof Error ? error : new Error(String(error));
148+
const err = error as Error;
149149
setError(errorTextByCode[err.message as FeedbackErrorCode] ?? errorGenericText);
150150
onSubmitError(err);
151151
}

packages/feedback/test/core/sendFeedback.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ describe('sendFeedback', () => {
294294
email: 're@example.org',
295295
message: 'mi',
296296
}),
297-
).rejects.toMatch('ERROR_GENERIC');
297+
).rejects.toThrow('ERROR_GENERIC');
298298
});
299299

300300
it('handles 0 transport error', async () => {
@@ -309,7 +309,7 @@ describe('sendFeedback', () => {
309309
email: 're@example.org',
310310
message: 'mi',
311311
}),
312-
).rejects.toMatch('ERROR_GENERIC');
312+
).rejects.toThrow('ERROR_GENERIC');
313313
});
314314

315315
it('handles 403 transport error', async () => {
@@ -324,7 +324,7 @@ describe('sendFeedback', () => {
324324
email: 're@example.org',
325325
message: 'mi',
326326
}),
327-
).rejects.toMatch('ERROR_FORBIDDEN');
327+
).rejects.toThrow('ERROR_FORBIDDEN');
328328
});
329329

330330
it('handles 200 transport response', async () => {
@@ -358,7 +358,7 @@ describe('sendFeedback', () => {
358358

359359
vi.advanceTimersByTime(30_000);
360360

361-
await expect(promise).rejects.toMatch('ERROR_TIMEOUT');
361+
await expect(promise).rejects.toThrow('ERROR_TIMEOUT');
362362

363363
vi.useRealTimers();
364364
});

0 commit comments

Comments
 (0)