# Troubleshooting the APIs

> The errors the storefront API, GraphQL and the MCP server answer with, what each one means and what to do about it.

Source: https://docs.bifrostorbit.com/commerce/developers/troubleshooting/

Every error from the storefront API has the same shape. The `message` is written so you can show it to a shopper as it is:

```json
{ "error": { "code": "conflict", "message": "Only 2 of Tind 2 tent are left" } }
```

Validation errors answer `422` with code `invalid` and add `issues`, one per field. GraphQL puts the same `message` in `errors`, with the code under `extensions.code`. See [GraphQL](https://docs.bifrostorbit.com/commerce/developers/graphql/) for its own codes, such as `query_too_deep`.

## Calls from the browser

| You see | Why | What to do |
| --- | --- | --- |
| `403` "This website isn't allowed to use this shop's cart. Add it to the allowed websites in Commerce Orbit's shop settings." | A cart, checkout or order call came from a website that isn't the shop's **Website** or under **Allowed websites**. | An Admin adds it under **Settings**, such as `https://northwilds.com`. Only the scheme, host and port count. Up to 20 can be listed. |
| A CORS error in the browser console, with no answer | The same as above. | As above. Reading products works from any website. |
| A CORS error on a request with your own headers | Only `Content-Type`, `Authorization` and `X-Api-Key` are allowed. | Leave out other headers. |
| `403` "A key that reads drafts must stay on your server…" | A `com_sk_` key was sent from a browser on another website. | Call from your server, or use a `com_pk_` key in the browser. |

## Keys and shops

| You see | Why | What to do |
| --- | --- | --- |
| `402` `subscription_inactive` | The Commerce Orbit trial or plan ended, so the shop is paused. | An owner chooses a plan under **Billing** in Orbit; everything answers again within a minute. Show your own "temporarily unavailable" message meanwhile. |
| `404` "Shop was not found" | The shop address in the URL doesn't exist, or changed. | Copy it from **Settings**, such as `northwilds`. |
| `401` "This API key isn't valid for this organisation…" | The key is wrong, or belongs to another shop. | Check the key under **API keys**. |
| `401` "This API key has been revoked…" or "…has expired…" | The key was revoked, or passed its expiry date. | Create a new key. A wrong key fails even on reads that need none. |
| `401` "Send an API key, or name the shop with ?organisation=…" | A GraphQL request with neither. | Add `?organisation=northwilds` or a key. |
| `404` "Product was not found" | No active product with that address or id. Draft products need a `com_sk_` key; archived ones are never returned. | Check the address, or the product's status. |

## Carts

| You see | Why |
| --- | --- |
| `404` "Cart was not found" | The token is wrong, or belongs to another shop. Start a new cart. |
| `409` "This cart has already been ordered. Start a new one." | The cart became a paid order, or an order on invoice. Start a new cart. |
| A line you added is missing | The variant id doesn't exist, or its product isn't active. Lines like that are dropped. |
| `422` "Enter a valid email address", "Use the two-letter country code" | A field is in the wrong format. `issues` lists each one. |
| `discountProblem`: "That code has expired" and similar | The code doesn't apply. It doesn't stop checkout; the cart is priced without it. |
| `problems`: "Storm shell jacket has no price in SEK" | The variant has no price in the cart's currency. Switch currency, or ask the shop to add the price. |
| `problems`: "Shipping has no price in SEK" | The chosen shipping rate has no price in the cart's currency. |
| `problems`: "Only 2 of Tind 2 tent are left", "Tind 2 tent is sold out" | Not enough stock. |
| `problems`: "Something in your cart is no longer for sale" | A product was made a draft, archived or binned. Remove the line with `lines`. |

## Checkout

| You see | Why |
| --- | --- |
| `400` "Your cart is empty", "Add your email address", "Add your name" | The cart is missing them. |
| `400` "Choose how you'd like it delivered", "Add the delivery address" | No `shipping`, or a delivery rate without `shippingAddress`. |
| `400` "Choose card or invoice" | `method` is something other than `card` or `invoice`. |
| `409` with the first entry of `problems` | Something in the cart stops checkout. Read the cart. |
| `409` "This shop can't take card payments yet" | The shop has no working Stripe connection, or its key lacks a permission. See [Connect your Stripe account](https://docs.bifrostorbit.com/commerce/everyone/connect-stripe/). |
| `409` "The payment couldn't start: …" | Stripe refused to create the payment, with Stripe's reason. Nothing was created. |
| `409` "Paying by invoice is only for companies with an account" | The cart's `company` is `null`, or its `terms` aren't `invoice`. |
| `409` "Your account is on hold. Contact us to order on invoice." | The company's MAM account is on stop. Card payment still works. |

### An order stays `pending`

After `stripe.confirmPayment`, read the order with its reference and email: it asks Stripe and marks the order paid if the payment went through. If nobody pays within the shop's stock reservation time, 15 minutes unless the shop changes it, the order is cancelled and its stock released. Don't call checkout again to retry a failed payment: let the shopper try again with the same `clientSecret`. See [Checkout with Stripe](https://docs.bifrostorbit.com/commerce/developers/checkout-with-stripe/).

## Orders

| You see | Why |
| --- | --- |
| `400` "Add the email address the order was placed with" | No `?email=`. |
| `404` "Order was not found" | The reference doesn't exist, or the email doesn't match the order's. Capitals in the email don't matter. |
| `409` "The receipt is ready once the payment has gone through" | The PDF of an order still waiting for its card payment. |

## Rate limits

`429` with "Too many tries. Wait a minute and try again." (GraphQL: "Too many requests…") means one address made too many requests in a short time. The limits are in [the storefront API](https://docs.bifrostorbit.com/commerce/developers/storefront-api/#rate-limits). If your server calls on behalf of many shoppers, all its calls share its address, so cache catalogue answers on your side.

## The MCP server

| You see | Why |
| --- | --- |
| `401` "Connect the assistant to Commerce Orbit again" | The token is missing, wrong or expired and couldn't be renewed. Connect again from the assistant. |
| `403` "The person who connected this assistant no longer has Commerce Orbit in the organisation" | Their access was removed in Orbit. |
| "Your Commerce Orbit role doesn't allow that. Ask an admin of your organisation." | A Viewer used `update_product_text`. Editors and Admins can. |
| `413` "The request is too large" | The request is over 1 MB. |
| "An order with that reference was not found" | `get_order` was given a reference that doesn't exist. Use `list_orders` to find it. |

## Something failed on our side

`500` with `server_error` means Commerce Orbit couldn't answer. Try again in a moment. The status of every Orbit service is at [docs.bifrostorbit.com/status](https://docs.bifrostorbit.com/status/).
