Error handling
Catch and respond to declines, invalid data, network problems, and more.
Stripe offers many kinds of errors. They can reflect external events, like declined payments and network interruptions, or code problems, like invalid API calls.
To handle errors, use some or all of the techniques in the table below. No matter what technique you use, you can follow up with our recommended responses for each error type.
Technique | Purpose | When needed |
---|---|---|
Catch exceptions | Recover when an API call can’t continue | Always |
Monitor webhooks | React to notifications from Stripe | Sometimes |
Get stored information about failures | Investigate past problems and support other techniques | Sometimes |
Catch exceptions
If an immediate problem prevents an API call from continuing, the Stripe Ruby library raises an exception. It’s a best practice to catch and handle exceptions.
To catch an exception, use Ruby’s rescue
keyword. Catch Stripe::StripeError
or its subclasses to handle Stripe-specific exceptions only. Each subclass represents a different kind of exception. When you catch an exception, you can use its class to choose a response.
After setting up exception handling, test it on a variety of data, including test cards, to simulate different payment outcomes.
Monitor webhooks
Stripe notifies you about many kinds of problems using webhooks. This includes problems that don’t follow immediately after an API call. For example:
- You lose a dispute.
- A recurring payment fails after months of success.
- Your frontend confirms a payment, but goes offline before finding out the payment fails. (The backend still receives webhook notification, even though it wasn’t the one to make the API call.)
You don’t need to handle every webhook event type. In fact, some integrations don’t handle any.
In your webhook handler, start with the basic steps from the webhook builder: get an event object and use the event type to find out what happened. Then, if the event type indicates an error, follow these extra steps:
- Access event.data.object to retrieve the affected object.
- Use stored information on the affected object to gain context, including an error object.
- Use its type to choose a response.
To test how your integration responds to webhook events, you can trigger webhook events locally. After completing the setup steps at that link, trigger a failed payment to see the resulting error message.
stripe trigger payment_intent.payment_failed
A payment error occurred: Your card was declined.
Get stored information about failures
Many objects store information about failures. That means that if something already went wrong, you can retrieve the object and examine it to learn more. In many cases, stored information is in the form of an error object, and you can use its type to choose a response.
For instance:
- Retrieve a specific payment intent.
- Check if it experienced a payment error by determining if last_payment_error is empty.
- If it did, log the error, including its type and the affected object.
Here are common objects that store information about failures.
Object | Attribute | Values |
---|---|---|
Payment Intent | last_ | An error object |
Setup Intent | last_ | An error object |
Invoice | last_ | An error object |
Setup Attempt | setup_ | An error object |
Payout | failure_ | A payout failure code |
Refund | failure_ | A refund failure code |
To test code that uses stored information about failures, you often need to simulate failed transactions. You can often do this using test cards or test bank numbers. For example:
- Simulate a declined payment, for creating failed Charges, PaymentIntents, SetupIntents, and so on.
- Simulate a failed payout.
- Simulate a failed refund.
Types of error and responses
In the Stripe Ruby library, error objects belong to stripe.
and its subclasses. Use the documentation for each class for advice on responding.
Name | Class | Description |
---|---|---|
Payment error | An error occurred during a payment, involving one of these situations: | |
Invalid request error | You made an API call with the wrong parameters, in the wrong state, or in an invalid way. | |
Connection error | There was a network problem between your server and Stripe. | |
API error | Something went wrong on Stripe’s end. (These are rare.) | |
Authentication error | Stripe can’t authenticate you with the information provided. | |
Idempotency error | You used an idempotency key for something unexpected, like replaying a request but passing different parameters. | |
Permission error | The API key used for this request does not have the necessary permissions. | |
Rate limit error | You made too many API calls in too short a time. | |
Signature verification error | You’re using webhook signature verification and couldn’t verify that a webhook event is authentic. |
Payment errors
Payment errors—sometimes called “card errors” for historical reasons—cover a wide range of common problems. They come in three categories:
To distinguish these categories or get more information about how to respond, consult the error code, decline code, and charge outcome.
(To find the charge outcome from an error object, first get the Payment Intent that’s involved and the latest Charge it created. See the example below for a demonstration.)
Users on API version 2022-08-01 or older:
(To find the charge outcome from an error object, first get the Payment Intent that’s involved and the latest Charge it created. See the example below for a demonstration.)
You can trigger some common kinds of payment error with test cards. Consult these lists for options:
The test code below demonstrates a few possibilities.
Payment blocked for suspected fraud
Type |
|
Codes |
|
Codes |
|
Problem | Stripe’s fraud prevention system, Radar, blocked the payment |
Solutions | This error can occur when your integration is working correctly. Catch it and prompt the customer for a different payment method. To block fewer legitimate payments, try these:
Radar for Fraud Teams customers have these additional options:
You can test your integration’s settings with test cards that simulate fraud. If you have custom Radar rules, follow the testing advice in the Radar documentation. |
Payment declined by the issuer
Type |
|
Codes |
|
Problem | The card issuer declined the payment. |
Solutions | This error can occur when your integration is working correctly. It reflects an action by the issuer, and that action may be legitimate. Use the decline code to determine what next steps are appropriate. See the documentation on decline codes for appropriate responses to each code. You can also:
Test how your integration handles declines with test cards that simulate successful and declined payments. |
Other payment errors
Type |
|
Problem | Another payment error occurred. |
Solutions | This error can occur when your integration is working correctly. Use the error code to determine what next steps are appropriate. See the documentation on error codes for appropriate responses to each code. |
Invalid request errors
Type |
|
Problem | You made an API call with the wrong parameters, in the wrong state, or in an invalid way. |
Solutions | In most cases, the problem is with the request itself. Either its parameters are invalid or it can’t be carried out in your integration’s current state.
|
Connection errors
Type |
|
Problem | There was a network problem between your server and Stripe. |
Solutions | Treat the result of the API call as indeterminate. That is, don’t assume that it succeeded or that if failed. To find out if it succeeded, you can:
To make it easier to recover from connection errors, you can:
This error can mask others. It’s possible that when the connection error resolves, some other error becomes apparent. Check for errors in all of these solutions just as you would in the original request. |
API errors
Type |
|
Problem | Something went wrong on Stripe’s end. (These are rare.) |
Solutions | Treat the result of the API call as indeterminate. That is, don’t assume that it succeeded or that it failed. Rely on webhooks for information about the outcome. Whenever possible, Stripe fires webhooks for any new objects we create as we solve a problem. To set your integration up for maximum robustness in unusual situations, see this advanced discussion of server errors. |
Authentication errors
Type |
|
Problem | Stripe can’t authenticate you with the information provided. |
Solutions |
|
Idempotency errors
Type |
|
Problem | You used an idempotency key for something unexpected, like replaying a request but passing different parameters. |
Solutions |
|
Permission errors
Type |
|
Problem | The API key used for this request does not have the necessary permissions. |
Solutions |
|
Rate limit errors
Type |
|
Problem | You made too many API calls in too short a time. |
Solutions |
|
Signature verification errors
Type |
|
Problem | You’re using webhook signature verification and couldn’t verify that a webhook event is authentic. |
Solutions | This error can occur when your integration is working correctly. If you use webhook signature verification and a third party attempts to send you a fake or malicious webhook, then verification fails and this error is the result. Catch it and respond with a If you receive this error when you shouldn’t—for instance, with webhooks that you know originate with Stripe—then see the documentation on checking webhook signatures for further advice. In particular, make sure you’re using the correct endpoint secret. This is different from your API key. |