Skip to content

Errors

Every error from the API has the same shape:

{
"error": {
"type": "invalid_request",
"message": "Payment intent not found.",
"details": {}
}
}

message is written to be read. It’s safe to log, and usually safe to show. details is there only for some errors. @usestack/node throws these as a StackError with type, status, message, details and requestId.

type HTTP Means What to do
invalid_request 400, 404, 409 Something in the request is wrong, or the thing doesn’t exist or isn’t yours. Fix the request. message says what.
authentication_failed 401 Missing, wrong or rolled key. Check the key, and that it’s the secret key on your server.
invalid_request 403 A live key while live mode isn’t open to you: not verified yet, or paused by Stack. See Going live. Your test keys keep working.
insufficient_balance 409 Your Stack balance can’t cover a refund. Try again once your balance covers it.
limit_exceeded 403 A live payment over a limit Stack set on your account (per payment or per month). Contact us, or take a smaller payment.
rate_limited 429 Too many requests. Back off and retry. @usestack/node does this for you.
internal 500 Something broke at Stack. Retry with the same idempotency key. If it keeps happening, contact us with the x-request-id.
network_error — @usestack/node only: Stack couldn’t be reached. Retry. The SDK already retried twice.

Errors during a payment are handled in the sheet: a declined card, a wrong code or PIN, an expired payment. The customer sees what happened and can try again, or choose another way to pay. You only see a result when the sheet closes:

  • presentPaymentSheet resolves with { status: 'failed', error: { type, message } } when a payment can’t go ahead, for example because it expired (intent_expired).
  • The customer’s own limits (limit_exceeded) and card declines (card_declined) are shown in the sheet and don’t close it.