# Error Reference

This page documents all error responses returned by the XOXNO Aggregator API, including HTTP status codes, causes, and resolution steps.

## Error Response Format

All API errors return a JSON body with an `error` field:

```json
{
  "error": "<error message>"
}
```

There is no nested `code` field; the error string is the canonical identifier. Match errors using substring checks against the patterns documented below.

***

## Application Errors (HTTP 400)

These errors indicate a problem with the request parameters. They will not resolve with a retry.

### Unknown Input Token

**Trigger**: The `from` parameter contains a token identifier the router does not recognize.

```json
{
  "error": "unknown token_in 'INVALID-123456'"
}
```

| Field         | Value                                                                                                                                                                     |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| HTTP status   | `400`                                                                                                                                                                     |
| Error pattern | `"unknown token_in"`                                                                                                                                                      |
| Cause         | Token not found in the router's token registry                                                                                                                            |
| Resolution    | Verify the token identifier format (`TICKER-hexcode`). Use [pair-config](https://docs.xoxno.com/developers/aggregator-api/pair-config) to confirm the token is supported. |

***

### Unknown Output Token

**Trigger**: The `to` parameter contains an unrecognized token identifier.

```json
{
  "error": "unknown token_out 'INVALID-123456'"
}
```

| Field         | Value                                                                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| HTTP status   | `400`                                                                                                                                 |
| Error pattern | `"unknown token_out"`                                                                                                                 |
| Cause         | Token not found in the router's token registry                                                                                        |
| Resolution    | Verify the token identifier format. Use [pair-config](https://docs.xoxno.com/developers/aggregator-api/pair-config) to check support. |

***

### No Route Found

**Trigger**: Both tokens are known, but no liquidity path connects them in the current pool graph.

```json
{
  "error": "routing failed: no path between tokens"
}
```

| Field         | Value                                                                                                                                                                                                     |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| HTTP status   | `400`                                                                                                                                                                                                     |
| Error pattern | `"no path between tokens"`                                                                                                                                                                                |
| Cause         | Insufficient liquidity or no pool chain linking the token pair                                                                                                                                            |
| Resolution    | Check [pair-config](https://docs.xoxno.com/developers/aggregator-api/pair-config). Try common intermediate tokens (WEGLD, USDC). Consider that newly listed tokens may not yet have sufficient liquidity. |

***

### Invalid Amount

**Trigger**: The `amountIn` or `amountOut` value is not a valid unsigned integer.

```json
{
  "error": "invalid amount_in: expected unsigned integer amount"
}
```

| Field         | Value                                                                                                                           |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| HTTP status   | `400`                                                                                                                           |
| Error pattern | `"invalid amount_in"` or `"invalid amount_out"`                                                                                 |
| Cause         | Amount is fractional, negative, zero, or non-numeric                                                                            |
| Resolution    | Pass amounts as stringified integers in the token's smallest units (no decimals). Example: `"1000000000000000000"` for 1 WEGLD. |

***

### Ambiguous Amount

**Trigger**: Both `amountIn` and `amountOut` are provided in the same request.

```json
{
  "error": "specify either amount_in or amount_out, not both"
}
```

| Field         | Value                                                                                                     |
| ------------- | --------------------------------------------------------------------------------------------------------- |
| HTTP status   | `400`                                                                                                     |
| Error pattern | `"specify either amount_in or amount_out"`                                                                |
| Cause         | The API cannot resolve direction when both amounts are specified                                          |
| Resolution    | Remove one of the two parameters. Use `amountIn` for a forward quote and `amountOut` for a reverse quote. |

***

### Missing Amount

**Trigger**: Neither `amountIn` nor `amountOut` is present in the request.

```json
{
  "error": "amount_in or amount_out must be provided"
}
```

| Field         | Value                                                     |
| ------------- | --------------------------------------------------------- |
| HTTP status   | `400`                                                     |
| Error pattern | `"amount_in or amount_out must be provided"`              |
| Cause         | No amount parameter was supplied                          |
| Resolution    | Add either `amountIn` or `amountOut` to the query string. |

***

### Simulation Failed

**Trigger**: The router found candidate paths but simulation failed for all of them.

```json
{
  "error": "simulation failed"
}
```

| Field         | Value                                                                                                       |
| ------------- | ----------------------------------------------------------------------------------------------------------- |
| HTTP status   | `400`                                                                                                       |
| Error pattern | `"simulation failed"`                                                                                       |
| Cause         | Typically caused by extremely low pool liquidity, an amount that would drain a pool, or overflow conditions |
| Resolution    | Reduce the trade size. Check that neither pool involved is near-empty.                                      |

***

## Infrastructure Errors

### Rate Limit Exceeded (HTTP 429)

**Trigger**: More than 100 requests per second from a single IP.

```json
{
  "error": "rate limit exceeded"
}
```

| Field       | Value                                                                                                          |
| ----------- | -------------------------------------------------------------------------------------------------------------- |
| HTTP status | `429`                                                                                                          |
| Cause       | Request rate exceeds 100 req/s per IP                                                                          |
| Resolution  | Implement exponential backoff. Use `includePaths=false` for high-frequency polling to reduce per-request cost. |

***

### Service Unavailable (HTTP 503)

**Trigger**: The service is starting up or pool data has not yet been loaded.

```json
{
  "error": "service unavailable"
}
```

| Field       | Value                                                                       |
| ----------- | --------------------------------------------------------------------------- |
| HTTP status | `503`                                                                       |
| Cause       | Cold start or pool data refresh in progress                                 |
| Resolution  | Retry with backoff. The service typically initializes within 10–30 seconds. |

***

## Error Summary Table

| Error message pattern                        | HTTP | Retryable | Resolution                            |
| -------------------------------------------- | ---- | --------- | ------------------------------------- |
| `"unknown token_in"`                         | 400  | No        | Fix token identifier                  |
| `"unknown token_out"`                        | 400  | No        | Fix token identifier                  |
| `"no path between tokens"`                   | 400  | No        | Use pair-config, try different tokens |
| `"invalid amount_in"`                        | 400  | No        | Pass integer in smallest units        |
| `"specify either amount_in or amount_out"`   | 400  | No        | Remove one amount parameter           |
| `"amount_in or amount_out must be provided"` | 400  | No        | Add an amount parameter               |
| `"simulation failed"`                        | 400  | Sometimes | Reduce amount; retry once             |
| HTTP 429                                     | 429  | Yes       | Exponential backoff                   |
| HTTP 503                                     | 503  | Yes       | Retry with backoff                    |

***

## Best Practices

### Validate Tokens Before Quoting

Call [pair-config](https://docs.xoxno.com/developers/aggregator-api/pair-config) before requesting a quote to catch unknown tokens and missing routes early. This produces a better user experience than surfacing raw API error strings.

```javascript
async function getValidatedQuote(from, to, amountIn) {
  const config = await fetch(
    `https://swap.xoxno.com/api/v1/pair-config?from=${from}&to=${to}`
  ).then(r => r.json());

  if (!config.supported) {
    // Provide a user-friendly message before hitting the quote endpoint
    throw new Error(config.error === 'unknown tokenOut'
      ? `Token ${to} is not supported`
      : `No route available between ${from} and ${to}`
    );
  }

  return fetch(`https://swap.xoxno.com/api/v1/quote?from=${from}&to=${to}&amountIn=${amountIn}`)
    .then(r => r.json());
}
```

### Handle 429 with Exponential Backoff

```javascript
async function fetchWithBackoff(url, maxRetries = 4) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url);

    if (response.status !== 429 && response.status !== 503) {
      return response;
    }

    if (attempt < maxRetries - 1) {
      const delay = 200 * Math.pow(2, attempt); // 200ms, 400ms, 800ms, 1600ms
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }

  throw new Error('Request failed after maximum retries');
}
```

### Use `includePaths=false` for Price Polling

Applications that poll quote prices at high frequency (e.g., updating a UI with real-time rates) should omit path details:

```javascript
const priceUrl = `https://swap.xoxno.com/api/v1/quote?\
from=${tokenIn}&to=${tokenOut}&amountIn=${amount}&includePaths=false`;
```

This reduces response payload size and avoids unnecessary computation on the server side.

***

## Related Topics

* [Quote Endpoint](https://docs.xoxno.com/developers/aggregator-api/quote) — Full parameter reference
* [Pair Configuration](https://docs.xoxno.com/developers/aggregator-api/pair-config) — Token validation
* [Integration Guide](https://docs.xoxno.com/developers/aggregator-api/integration-guide) — Retry logic and error handling patterns
