# Errors

The Canon API uses standard HTTP status codes and returns structured JSON error responses.

## Error Response Format

All errors return a JSON object with an `error` field. Validation errors additionally include a `detail` field:

```json
{
  "error": "validation_error",
  "detail": "invalid asset: FAKECOIN"
}
```

## HTTP Status Codes

| Code | Meaning | Description |
|---|---|---|
| `200` | OK | Request succeeded |
| `400` | Bad Request | Invalid request parameters |
| `401` | Unauthorized | Missing or invalid API key |
| `404` | Not Found | Resource not found (e.g. no volatility data for requested backtest asset) |
| `429` | Too Many Requests | Rate limit exceeded |
| `500` | Internal Server Error | Unexpected server error |
| `502` | Bad Gateway | Upstream data source unavailable |
| `503` | Service Unavailable | Service is starting up or circuit breaker is open |
| `504` | Gateway Timeout | Risk computation exceeded 10 second timeout |

## Authentication Errors (401)

Missing or malformed `Authorization` header:

```json
{
  "error": "missing or invalid Authorization header"
}
```

Invalid API key:

```json
{
  "error": "invalid API key"
}
```

## Validation Errors (400)

All validation errors return `"error": "validation_error"` with a specific `detail` message:

```json
{
  "error": "validation_error",
  "detail": "leverage 100 exceeds maximum 50"
}
```

| Detail pattern | Description |
|---|---|
| `invalid asset: {name}` | Asset not found or not available on Hyperliquid |
| `invalid wallet address: {addr}` | Wallet address is not a valid 42-character hex address |
| `size must be positive, got {n}` | Position size is not positive |
| `size {n} exceeds maximum allowed {max}` | Position size exceeds $100M maximum |
| `leverage {n} exceeds maximum {max}` | Requested leverage exceeds the asset's maximum |
| `asset {name} is delisted and cannot be traded` | Asset has been delisted |
| `asset {name} only supports isolated margin mode` | Asset only supports isolated margin; cross margin was requested |

Batch-specific errors:

| Error | Detail | Description |
|---|---|---|
| `batch_too_large` | `max 50 trades per batch` | Batch request exceeds 50 trades |
| `validation_error` | `trades array is empty` | Batch request contains no trades |

## Upstream Errors (502)

Returned when Canon cannot fetch required data from the exchange.

```json
{
  "error": "l2_book_fetch_failed"
}
```

```json
{
  "error": "wallet_state_unavailable"
}
```

## Service Unavailable (503)

Returned when the service is still starting up and caches are not yet populated:

```json
{
  "error": "service_starting"
}
```

Also returned when the upstream circuit breaker is open due to repeated failures.

## Gateway Timeout (504)

Returned when risk computation exceeds the 10-second handler timeout:

```json
{
  "error": "timeout",
  "detail": "risk computation exceeded 10s"
}
```
