Error Handling for Relay Apps

This guide helps you test and gracefully handle errors returned by the Relay API to build a great checkout experience. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

The Relay API lets you place orders with a large numbers of merchants through a single simple API. Sometimes, however, a merchant can't fulfill an order because a given product is out of stock or because some piece of customer data is missing. The Relay API abstracts all retailer-specific error handling from you to let you worry about only a small set of errors related to SKUs and orders.

SKU-level errors

These errors are caused by a specific SKU. The error response will always contain a value for "params" of the form "items[{index}]" where {index} will be the index of the SKU that triggered the error. For example, if the SKU you tried to order from a retailer is out of stock, the Stripe API will respond with:

  "error": {
    "code": "out_of_inventory",
    "param": "items[0]",
    "message": "This SKU cannot be used to create an order: sku_80jcxrvoPNd57O is out of stock",
    "type": "invalid_request_error"

The following are example codes for SKU-level errors:

  • sku_inactive: The SKU is no longer available for purchase and will not be back in stock.
  • out_of_inventory: The SKU is no longer in stock.
  • product_inactive: The product this SKU belongs to is no longer available for purchase.
  • maximum_sku_quantity_exceeded: The merchant does not allow ordering this many of the given SKU.
  • upstream_price_mismatch: The price that the retailer has does not match Stripe’s price. You should update the price displayed to the customer and let them try placing their order again.

Order-level errors

These errors are triggered by the shipping address, billing address, email, or phone number of the order but not a specific SKU. If the error was caused by a single parameter, the response will contain a value for the field "params". For example, if the merchant failed to calculate shipping because of an issue with the customer’s postal code, the Stripe API will respond with:

  "error": {
    "code": "shipping_calculation_failed",
    "param": "shipping.address.postal_code",
    "message": "Shipping calculation failed: The zip code `123456` is not a valid.",
    "type": "invalid_request_error"

The possible order-level errors are:

  • order_required_parameter: The merchant is missing one or more fields before they can process the order. You should prompt the user to fill out this information based on the contents of "param".
  • address_verification_failed: The merchant could not verify the shipping or billing address. The value of "params" will tell you which field (if any) caused the validation error. You should prompt the user to update those fields.
  • shipping_calculation_failed: The merchant failed to calculate a set of valid shipping options. If "params" is specified, you should prompt the user to update that field.
  • taxes_calculation_failed: The merchant failed to calculate tax for the order. If "params" is specified, you should prompt the user to update the field it refers to.
  • order_creation_failed: Generic error code to indicate that order creation failed. It is safe to retry creating the order.
  • order_payment_failed: Generic error code to indicate that order payment failed. It is safe to retry paying the order.

When the error pertains to a specific request parameter, the possible values for "param" are:

  • email
  • shipping.address
  • card.address

The address fields above (shipping.address and card.address) can refer to a more specific component of the address. For example, an issue with the shipping address can also return the "param":

  • shipping.address.line1
  • shipping.address.line2
  • shipping.address.state
  • shipping.address.postal_code

Testing your application

To help you test your error handling easily and deterministically, we have set up a test merchant that will send back an error response solely based on your API request. This merchant (acct_17ki35KuoS4pPl69) has a dummy T-shirt for sale with ID stripe_shirt and three different sizes (S, M, L). This merchant is set up to only accept test mode requests, so you should only use this connection for testing your Relay app.

If you have not yet built your Relay Connect app, consider building a basic checkout experience using the Relay Demo catalog. To get started with advanced error handling, connect your application to our test account below:

This merchant looks at two pieces of data when determining which error to return: SKU quantity and shipping address. The SKU quantity determines which error gets returned and the shipping address determines which value of "param" (if any) gets returned along with that error. Below are the quantities that will trigger an error. Note that if your order contains more than one SKU, the first SKU with a quantity greater than 1 will be used to determine the error returned.

When you create an order with the given SKU quantities, the Stripe API returns one of the following error codes:

Quantity Error
1 No error
2 sku_inactive
3 out_of_inventory
4 product_inactive
5 maximum_sku_quantity_exceeded
6 upstream_price_mismatch
7 upstream_coupon_code_invalid
8 shipping_calculation_failed
9 taxes_calculation_failed
10 address_verification_failed
11 order_required_parameter
12 order_creation_failed

When you pay for an order, the Stripe API returns one of the following error codes:

Quantity Error
20 order_payment_failed
21 order_required_parameter

The other component controlling the error is the first line of the shipping address on the order (shipping[address][line1] in your request). If the first line of the address contains "XXX Main Street" and XXX is specified in the table below, the given parameter will be returned in the "param" of the error response.

Address Param
1600 "shipping.address.line1"
1601 "shipping.address.line2"
1602 ""
1603 "shipping.address.postal_code"
1604 "shipping.address.state"
1605 ""
1606 "shipping.address"
1607 ""
1608 ""
1700 "card.address.line1"
1701 "card.address.line2"
1702 ""
1703 "card.address.postal_code"
1704 "card.address.state"
1705 ""
1706 "card.address"
1707 ""
1800 "email"

For example, the following request specifies quantity 8 and the address "1604 Main Street". Based on the tables above, we know the response will have the error code "shipping_calculation_failed" and include the parameter "shipping.address.state":

curl \
 -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
 -H "Stripe-Account: acct_17ki35KuoS4pPl69" \
 -d items[][type]=sku \
 -d items[][parent]=stripe_shirt_large \
 -d items[][quantity]=8 \
 -d currency=usd \
 -d shipping[name]="Jenny Rosen" \
 -d shipping[address][line1]="1604 Main Street" \
 -d shipping[address][city]=Anytown \
 -d shipping[address][postal_code]=123456 \
 -d shipping[address][state]=CA \
 -d shipping[address][country]=US
  "error": {
    "type": "invalid_request_error",
    "code": "shipping_calculation_failed",
    "param": "shipping.address.state",
    "message": "Shipping calculation failed: Couldn't verify your shipping address"

Get in touch

If you notice anything surprising, or have feedback or more importantly questions, please get in touch!

More about Relay

Looking to learn more about Relay? Check out these other guides: