Profiles·Public

stripe

semver>=21.0.0postconditions16functions7last verified2026-06-15coverage score86%

Postconditions — what we check

  • constructEvent · wrong-webhook-parsing-method
    error
    WhenconstructEvent() called with a v2 event-notification payload, or with a payload generated by a webhook destination that expects parseEventNotification()
    ThrowsStripeError — v21 added an explicit guard that throws when the wrong parsing method is used
    Required handlingUse parseEventNotification() for v2 thin events (EventNotifications) and constructEvent() for v1 events. Inspect the webhook destination type before choosing which method to call. Wrap both in try/catch and surface a 400.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • constructEventAsync · wrong-webhook-parsing-method
    error
    WhenconstructEventAsync() called with a v2 event-notification payload, or payload from a destination that expects parseEventNotification()
    ThrowsStripeError — v21 added an explicit guard that throws when the wrong parsing method is used
    Required handlingUse parseEventNotification() for v2 thin events and constructEventAsync() for v1.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • token · oauth-invalid-grant
    error
    WhenAuthorization code is expired, already used, doesn't exist, or live/test mode mismatch with API key
    ThrowsStripeInvalidGrantError (extends StripeOAuthError)
    Required handlingCatch StripeInvalidGrantError specifically OR catch the StripeOAuthError parent. Surface a user-facing "authorization expired, please reconnect" message; redirect the user back through the OAuth start URL. DO NOT retry — codes are single-use.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3][4]
  • token · oauth-invalid-client
    error
    Whenclient_id does not belong to your platform, or an API key is required but not provided
    ThrowsStripeInvalidClientError (extends StripeOAuthError)
    Required handlingCatch StripeInvalidClientError or the StripeOAuthError parent. This is a configuration error — log and alert ops, do not retry, do not show user a redirect (the OAuth setup is broken on your side).
    costcriticalin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • token · oauth-invalid-request
    error
    WhenRequired OAuth parameter missing, or unsupported parameter/value provided
    ThrowsStripeOAuthInvalidRequestError (extends StripeOAuthError)
    Required handlingCatch StripeOAuthInvalidRequestError or the StripeOAuthError parent. Indicates malformed request from your code — fix and redeploy, do not retry.
    Sources[3]
  • token · oauth-invalid-scope
    error
    WhenInvalid scope value provided in OAuth request
    ThrowsStripeInvalidScopeError (extends StripeOAuthError)
    Required handlingCatch StripeInvalidScopeError or the StripeOAuthError parent. Fix the scopes list in your OAuth start URL.
    Sources[3]
  • token · oauth-unsupported-grant-type
    error
    WhenUnsupported grant_type parameter in OAuth request
    ThrowsStripeUnsupportedGrantTypeError (extends StripeOAuthError)
    Required handlingCatch StripeUnsupportedGrantTypeError or the StripeOAuthError parent. Use authorization_code or refresh_token; consult Stripe Connect docs.
    Sources[3]
  • deauthorize · oauth-invalid-grant
    error
    WhenStripe user id is invalid or the access token has already been revoked
    ThrowsStripeInvalidGrantError (extends StripeOAuthError)
    Required handlingCatch StripeInvalidGrantError or the StripeOAuthError parent. Surface a message that the account is already disconnected; do not retry.
    Sources[3][5]
  • deauthorize · oauth-invalid-client
    error
    Whenclient_id does not belong to your platform
    ThrowsStripeInvalidClientError (extends StripeOAuthError)
    Required handlingCatch StripeInvalidClientError or the StripeOAuthError parent. Configuration error — fix client_id, do not retry.
    Sources[3]
  • parseEventNotification · parse-event-notification-signature-failed
    error
    WhenWebhook payload signature is invalid — wrong signing secret, tampered payload, or expired timestamp (outside DEFAULT_TOLERANCE of 300s). Signature check happens via webhooks.signature.verifyHeader() called inside parseEventNotification.
    ThrowsStripeSignatureVerificationError (extends StripeError)
    Required handlingWrap stripe.parseEventNotification() in try-catch. Catch StripeSignatureVerificationError specifically and return HTTP 400 to Stripe. DO NOT process the event if signature verification fails — the payload cannot be trusted. Unlike constructEvent, parseEventNotification processes v2 thin events, so the same security requirement applies with equal urgency.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[6][1]
  • parseEventNotification · parse-event-notification-wrong-payload-type
    error
    WhenA v1 event payload (event.object === 'event') is mistakenly passed to parseEventNotification(). The implementation explicitly checks for this and throws a plain Error with message: "You passed a webhook payload to stripe.parseEventNotification, which expects an event notification. Use stripe.webhooks.constructEvent instead." Conversely, passing a v2 thin event to constructEvent() throws the inverse guard. Both guards were added in stripe-node v21 (PR #2618).
    ThrowsError (plain JavaScript Error, not StripeError)
    Required handlingUse parseEventNotification() for v2 thin events (event_payload: 'thin' destination) and stripe.webhooks.constructEvent() for v1 events (event_payload: 'snapshot'). Inspect the webhook destination configuration before choosing the parsing method. A catch block on StripeError alone will NOT catch this — it's a plain Error. Wrap in generic try-catch: catch (e) { if (e instanceof Error) return res.status(400)... }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[7][1][2]
  • fetchRelatedObject · fetch-related-object-no-try-catch
    error
    WhenNetwork failure (DNS, TCP, TLS), API authentication error, or server error while fetching the related object from Stripe's v2 API. The HTTP GET is made using the same request pipeline as all other Stripe API calls, meaning all StripeConnectionError (network), StripeAuthenticationError (bad API key), StripeAPIError (5xx), and StripeRateLimitError conditions apply.
    ThrowsStripeConnectionError | StripeAuthenticationError | StripeAPIError | StripeRateLimitError
    Required handlingAlways await eventNotification.fetchRelatedObject() inside a try-catch block. Note that null is returned (not thrown) when there is no related_object — this is a silent case that must also be checked: if (!related) return; or a nullish check before using the result. Network failures in webhook handlers cause silent failures if the catch block re-throws without surfacing a 500.
    costmediumin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[7][8]
  • fetchRelatedObject · fetch-related-object-temporary-session-expired
    error
    WhenThrows TemporarySessionExpiredError (rawType: 'temporary_session_expired') when the StripeContext attached to the event notification has expired. StripeContext is a v21 addition that scopes v2 API requests to a specific event — if the session window has passed, the context-authenticated request is rejected. This error class is NEW in v21 and does NOT extend StripeRateLimitError — a catch block for StripeRateLimitError will NOT catch it. Confirmed from cjs/Error.js: generateV2Error dispatches 'temporary_session_expired' to new TemporarySessionExpiredError (rawType: 'temporary_session_expired').
    ThrowsTemporarySessionExpiredError (extends StripeError, rawType: 'temporary_session_expired')
    Required handlingCatch TemporarySessionExpiredError explicitly. The standard pattern is to re-fetch the event from the v2 events API: stripe.v2.core.events.retrieve(id). Do NOT retry the same fetchRelatedObject() call — the session is permanently expired. Failing to handle this will silently drop the event's side-effect processing.
    costmediumin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[9][10]
  • fetchRelatedObject · fetch-related-object-null-unchecked
    warning
    WhenfetchRelatedObject() returns Promise<null> (not throws) when the EventNotification has no related_object field. This is a confirmed behavior from cjs/stripe.core.js: if (!eventNotification.related_object) { return Promise.resolve(null); }. Code that destructures or accesses properties on the result without a null check will throw a TypeError at runtime.
    ThrowsTypeError (null property access — NOT a StripeError, thrown by caller code)
    Required handlingAlways check the return value before use: const related = await notification.fetchRelatedObject(); if (!related) return; // notification has no related object This is NOT a Stripe SDK error but a caller-side TypeError from null access. Particularly dangerous in typed TypeScript where the return type is typed as Promise<T> and developers assume non-null.
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[7]
  • fetchEvent · fetch-event-no-try-catch
    error
    WhenNetwork failure, authentication error, or server error while fetching the full event from /v2/core/events/{id}. Same error types apply as all Stripe v2 API calls: StripeConnectionError (network), StripeAuthenticationError (invalid key), StripeAPIError (5xx), StripeRateLimitError (v1 path) or RateLimitError (v2 path).
    ThrowsStripeConnectionError | StripeAuthenticationError | StripeAPIError | StripeRateLimitError | RateLimitError
    Required handlingAlways await eventNotification.fetchEvent() inside a try-catch block. A common anti-pattern is calling fetchEvent() only when needed (e.g., inside a switch/case handler) without wrapping the call — the outer catch block from parseEventNotification() does NOT cover async calls made after the synchronous parse.
    costmediumin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[7][8]
  • fetchEvent · fetch-event-temporary-session-expired
    error
    WhenThrows TemporarySessionExpiredError when the StripeContext session has expired. Same mechanism as fetchRelatedObject — the context is scoped to the event notification and expires after a window. Confirmed from cjs/Error.js generateV2Error dispatch. This is the same new v21-specific error class as in fetchRelatedObject.
    ThrowsTemporarySessionExpiredError (extends StripeError, rawType: 'temporary_session_expired')
    Required handlingCatch TemporarySessionExpiredError explicitly. Re-fetch the event using stripe.v2.core.events.retrieve(eventId) with standard Stripe API authentication instead of the context-scoped fetchEvent() call. Log the expired context for monitoring — frequent expiry indicates delayed webhook processing.
    costmediumin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[9][11]

Sources

Every postcondition cites at least one of these. Numbered to match the footnotes above.

  1. [1]github.com/stripe/stripe-nodehttps://github.com/stripe/stripe-node/pull/2618
  2. [2]github.com/stripe/stripe-nodehttps://github.com/stripe/stripe-node/blob/v21.0.0/CHANGELOG.md
  3. [3]raw.githubusercontent.com/stripe/stripe-nodehttps://raw.githubusercontent.com/stripe/stripe-node/v21.0.0/src/Error.ts
  4. [4]stripe.com/docs/connecthttps://stripe.com/docs/connect/oauth-reference
  5. [5]stripe.com/docs/connecthttps://stripe.com/docs/connect/oauth-reference#post-deauthorize
  6. [6]raw.githubusercontent.com/stripe/stripe-nodehttps://raw.githubusercontent.com/stripe/stripe-node/v21.0.1/cjs/Webhooks.js
  7. [7]raw.githubusercontent.com/stripe/stripe-nodehttps://raw.githubusercontent.com/stripe/stripe-node/v21.0.1/cjs/stripe.core.js
  8. [8]raw.githubusercontent.com/stripe/stripe-nodehttps://raw.githubusercontent.com/stripe/stripe-node/v21.0.1/cjs/RequestSender.js
  9. [9]raw.githubusercontent.com/stripe/stripe-nodehttps://raw.githubusercontent.com/stripe/stripe-node/v21.0.1/cjs/Error.js
  10. [10]raw.githubusercontent.com/stripe/stripe-nodehttps://raw.githubusercontent.com/stripe/stripe-node/v21.0.1/types/Errors.d.ts
  11. [11]docs.stripe.com/contexthttps://docs.stripe.com/context
Need a different package?
Request a profile