-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathbilling.stripe-errors.js
More file actions
33 lines (31 loc) · 1.69 KB
/
billing.stripe-errors.js
File metadata and controls
33 lines (31 loc) · 1.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* Classify Stripe errors for retry / short-circuit decisions.
*
* stripe-node sets `err.type` to the error CLASS NAME (Error.js: `this.type = type || this.constructor.name`,
* and every subclass passes its own name via `super(raw, 'StripeXError')`), while the raw API error type
* string (e.g. `'invalid_request_error'`) lives on `err.rawType`. Unwrapped/raw API error objects instead
* carry the wire type directly on `.type`. Both shapes are handled below.
*/
const NON_TRANSIENT_STRIPE_ERROR_CLASSES = new Set([
'StripeInvalidRequestError', // 400/404 — bad params, deterministic
'StripeIdempotencyError', // 400 — idempotency key reused with conflicting params, deterministic
'StripeAuthenticationError', // 401 — bad/missing API key, deterministic
'StripePermissionError', // 403 — key lacks permission for the resource, deterministic
]);
/**
* True when a Stripe error is deterministic and will never succeed on retry
* (invalid request, idempotency, authentication, or permission failures). Transient
* errors (api_error/500, connection, rate_limit/429) return false so they keep
* retrying. StripeCardError (402) is intentionally excluded — some decline codes
* (processing_error, issuer_unavailable) are transient.
*
* @param {unknown} err
* @returns {boolean}
*/
export function isNonTransientStripeError(err) {
if (!err || typeof err !== 'object') return false;
// SDK-wrapped errors expose the class name on `.type`.
if (NON_TRANSIENT_STRIPE_ERROR_CLASSES.has(err.type)) return true;
// SDK mirrors the wire type on `.rawType`; unwrapped API error objects carry it on `.type`.
return err.rawType === 'invalid_request_error' || err.type === 'invalid_request_error';
}