> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sunrise.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Every error code the Sunrise API sends, what it means, and what to do next.

Every error has a `code` and a `message`. Use `code` to decide what to do next. Show `message` to your user: it's written for them.

## Error shape

```json theme={null}
{
  "success": false,
  "error": {
    "code": "invalid_request",
    "message": "The request isn't valid.",
    "details": { "fields": ["fromAmount"] }
  },
  "requestId": "134bfdc0-d88a-45ab-9511-10977fb6020d",
  "timestamp": "2026-10-23T21:35:56.334Z"
}
```

| Field | What it holds |
| - | - |
| `error.code` | One code from the tables below. Each code means one next step. |
| `error.message` | The reason in plain words, safe to show your user. |
| `error.details.fields` | The request fields that aren't valid. Only on `invalid_request`. |
| `error.details.txHash` | The hash of the order's transaction, which was sent to Solana. Only on `transaction_failed` and `transaction_expired`. |
| `requestId` | Identifies the request. Also sent as the `X-Request-Id` header. |

Every response includes `requestId`, except a `401` for a missing or malformed API key and a `429 rate_limited`. Those carry only `success` and `error`.

## Codes you don't recognize

New codes may be added. When you get a code you don't handle yet:

* On a `409`, get a new quote.
* On a `5xx` from `POST /v1/execute`, send the same request again. Never sign a new quote: the order may already have been sent.

## When a route gives no quote

A missing quote isn't an error. `POST /v1/quotes` answers `200` with the quotes it found, and lists each route that gave none in `unavailableRoutes`, with why:

```json theme={null}
{
  "success": true,
  "data": {
    "quotes": [],
    "unavailableRoutes": [
      {
        "routeName": "titan",
        "code": "no_quote",
        "message": "No quote is available right now. Try again in a moment."
      },
      {
        "routeName": "dflow",
        "code": "pair_not_supported",
        "message": "This pair can't be traded."
      }
    ]
  },
  "requestId": "36de6a2c-5d0c-4398-a57f-fec563b11b9b",
  "timestamp": "2026-10-23T21:44:07.644Z"
}
```

`routeName` is absent when no route was asked, for example for a token Sunrise doesn't trade. The most common codes:

| Code | Message | What to do |
| - | - | - |
| `amount_too_small` | This amount is below the minimum for this trade. Try a larger amount. | Ask for a larger amount. |
| `amount_too_large` | This amount is above the maximum for this trade. Try a smaller amount. | Ask for a smaller amount. |
| `amount_not_on_step` | This exact amount can't be traded. Try a slightly different amount. | Ask for a slightly different amount. |
| `pair_not_supported` | This pair can't be traded. | Offer a different pair. |
| `integrator_fee_not_supported` | This route can't charge an integrator fee. | Quote without a fee to use this route. See [Integrator fees](https://docs.sunrise.xyz/recipes/integrator-fees.md). |
| `market_closed` | This market is closed right now. Try again when it opens. | Ask again when the market opens. |
| `trading_paused` | Trading in this asset is paused right now. Try again later. | Ask again later. |
| `no_liquidity` | No one is offering this trade right now. Try again in a moment. | Ask again in a moment. |
| `no_quote` | No quote is available right now. Try again in a moment. | Ask again in a moment. |

A route can also report any other code from this page. Its `message` is always safe to show your user.

## Request errors

| Code | Status | Message | What to do |
| - | - | - | - |
| `invalid_request` | 400 | The request isn't valid. | Fix the fields named in `details.fields`. Some refusals name none, such as a body that isn't JSON. |
| `integrator_fee_unavailable` | 400 | Integrator fees are not available for this API key. Contact Sunrise to enable them. | Contact Sunrise to enable fees, or quote without a fee. See [Integrator fees](https://docs.sunrise.xyz/recipes/integrator-fees.md). |
| `invalid_token` | 400 | This token address isn't valid. | Check the token address. |
| `token_not_supported` | 400 | This token isn't supported. | Choose a different token. |
| `invalid_transaction` | 400 | This transaction doesn't match the quote. Sign the quote's transaction without changing it. | Sign the quote's `unsignedTransaction` exactly as returned. |
| `unauthorized` | 401 | The API key is missing or invalid. | Check the API key. |
| `forbidden` | 403 | This API key can't make this request. | Contact Sunrise about your key's access. |
| `geo_blocked` | 403 | This trade isn't available in your region. | Don't offer this trade to the user. |
| `address_blocked` | 403 | This wallet address can't be used. | Don't use this wallet. |
| `trading_halted` | 403 | Trading in this asset is halted. | Don't offer this asset until trading resumes. |
| `not_found` | 404 | Not found. | Check the path or the token address. From `GET /v1/orders/{txHash}`, no order is listed for the transaction yet: try again in a minute. |
| `method_not_allowed` | 405 | This method isn't allowed here. | Use the method the API reference lists. |
| `payload_too_large` | 413 | The request is too large. | Send a smaller request body. |
| `rate_limited` | 429 | Too many requests. Wait a moment and try again. | Wait, then try again. `Retry-After`, when present, gives the seconds to wait. |
| `verification_rate_limited` | 429 | Too many requests. Wait a moment and try again. | Wait the seconds in `Retry-After`, then try again. |

Don't retry a `4xx` other than `429` unchanged: the same request gets the same answer.

## Order errors

These come from `POST /v1/execute`.

| Code | Status | Message | What to do |
| - | - | - | - |
| `quote_expired` | 409 | This quote has expired. Get a new quote and try again. | Get a new quote. |
| `price_moved` | 409 | The price changed before the order was placed. Get a new quote and try again. | Get a new quote. |
| `order_not_placed` | 409 | This order couldn't be placed. Get a new quote and try again. | Get a new quote. |
| `market_closed` | 409 | This market is closed right now. Try again when it opens. | Get a new quote when the market opens. |
| `trading_paused` | 409 | Trading in this asset is paused right now. Try again later. | Get a new quote later. |
| `no_liquidity` | 409 | No one is offering this trade right now. Try again in a moment. | Get a new quote in a moment. |
| `insufficient_sol` | 422 | Your wallet needs a little more SOL to place this order. | Add SOL to the wallet, then get a new quote. |
| `insufficient_balance` | 422 | Your wallet doesn't have enough of the token you're paying with. | Add funds or lower the amount, then get a new quote. |
| `simulation_failed` | 422 | This order would fail, so it wasn't sent. Get a new quote and try again. | Get a new quote. Nothing was sent. |
| `transaction_expired` | 422 | The order wasn't confirmed in time, so nothing was traded. Get a new quote and try again. | Get a new quote. `details.txHash` names the transaction that was sent. |
| `transaction_failed` | 422 | The order failed on the network. Get a new quote and try again. | Get a new quote. `details.txHash` names the failed transaction. |

A `409` means the order was refused before it was sent. A `422` means the order can't go through as signed.

## Server errors

| Code | Status | Message | What to do |
| - | - | - | - |
| `internal_error` | 500 | Something went wrong on our side. | Try again later. |
| `bad_gateway` | 502 | Something went wrong on our side. Try again in a moment. | Try again in a moment. |
| `service_unavailable` | 503 | The service is temporarily unavailable. Try again in a moment. | Try again in a moment. |
| `execute_status_unknown` | 503 | We couldn't confirm this order yet. Send the same request again to check; don't place a new order. | Send the same execute request again. |

> [!WARNING]
>
> On any `5xx` from `POST /v1/execute`, the order may already have been sent. Send the same request, with the same signed transaction, until `data.done` is `true` or it returns another error. Sending it again is safe: a signed transaction is executed at most once. Never sign a new quote: that can place the order twice.

See [Swap with the API](https://docs.sunrise.xyz/recipes/swap.md) for an execute loop that follows these rules.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.