# Errors

> The shape of an API error, what each status code means, and the errors specific to each resource.

Developers · Reference · https://wxalerts.org/docs/developers/errors/

## Error shape

Errors carry a JSON body. The key and rate limit errors put a machine-readable
`code` in `detail`:

```json
{ "detail": { "code": "api_key_required", "message": "This endpoint needs an API key: it is served at /v1/alerts/active. ..." } }
```

## Status codes

| status | means |
| --- | --- |
| `400` | a bad request the route explains, such as `key_in_query` |
| `401` | `api_key_required` (a key-only route without a key) or `api_key_invalid` |
| `403` | `insufficient_scope`: the key lacks the route's scope |
| `404` | nothing by that id, or a point outside the product's coverage |
| `422` | a parameter is missing or out of range; `detail` lists which |
| `429` | `rate_limited`: wait `Retry-After` seconds |
| `503` | the data behind the route is not available yet; try again later |

The key errors, with what to do about each, are on
[Authentication](/docs/developers/authentication/#errors). The limits behind
`429` are on [Rate limits](/docs/developers/rate-limits/).

## By resource

Each table lists only what is particular to that resource. A route that is not
listed here uses the codes above and nothing more.

### Alerts

| status | when |
| --- | --- |
| `401` | a key-only route on the bare path (`api_key_required`), or a `/v1` route without a valid key |
| `404` | no alert for that identifier or short id |
| `410` | `/alerts/page/{short_id}` for an alert past the 30 day retention window |
| `422` | a parameter out of range or missing, or a box with `west >= east` or `south >= north` |
| `429` | over a [rate limit](/docs/developers/rate-limits/); wait for `Retry-After` |

### Statistics

| status | when |
| --- | --- |
| `422` | an unknown `timezone`. It is never a silent fall back to UTC |

### SPC outlooks

| status | when |
| --- | --- |
| `404` | not a product slug. The `detail` lists every valid one |
| `503` | a real product that has never been fetched on this deployment. Retry later rather than dropping it from a menu |

### Weather

| status | when |
| --- | --- |
| `200` | a point outside the forecast coverage returns `hourly` and `daily` empty, not `404`. There is no error to handle |

### Forecast

| status | when |
| --- | --- |
| `404` | `q` with no match, or an unknown `location_id` |
| `422` | none of `lat`/`lon`, `q` or `location_id`, or an `include` value other than `severe` or `upper_air` |

### Point soundings

| status | when |
| --- | --- |
| `404` | a point outside the HRRR grid, or a `q` or `location_id` that matches nothing |
| `422` | none of `lat`/`lon`, `q` or `location_id` |
| `503` | no model run on hand |

### Raw model data

| status | means |
| --- | --- |
| `400` | the key was sent in the URL |
| `401` | no key, or an unknown, revoked or expired one |
| `403` | the key is not enabled for this endpoint (`admin_key_required`), or lacks `weather:read` |
| `404` | the point is outside the model's grid |
| `422` | a parameter that cannot be satisfied: an unknown field, two ways of choosing hours, `forecast_hours` with `nbm`. The message says which |
| `429` | over the limit; wait `Retry-After` seconds |
| `503` | the model has no run available yet |

### Observations

| status | when |
| --- | --- |
| `404` | a `q` or `location_id` that matches nothing, or a station id no station has |
| `422` | no point at all, or a malformed, inverted or oversized `bbox`. The message says which |

A known station with nothing in the history window returns `200` with
`count: 0`.

### Sunrise and sunset outlook

| status | when |
| --- | --- |
| `422` | a missing or out of range coordinate. There is no place name or `location_id` form |

### Low visibility

| status | when |
| --- | --- |
| `404` | on `/visibility/point`, a `q` or `location_id` that matches nothing |
| `422` | a `bbox` that is missing, malformed or too large, or no point on `/visibility/point` |
| `503` | before the first analysis has been published; retry |

### Storm cells

| status | when |
| --- | --- |
| `401` | a key-only route without `/v1` and a key, or a bad key on any route |
| `404` | `No such storm.` or `No such couplet.` on the detail, cone and forecast routes |
| `409` | the storm or couplet exists but has no motion fit yet, so it has no cone or forecast line. Normal on a first scan; try again next scan |
| `422` | a parameter out of range, an unknown `profile`, three of the four bounding box edges, or an inverted box |

### Lightning

| status | when |
| --- | --- |
| `422` | `bbox` missing, not four numbers, out of range or inverted, or `minutes` or `limit` out of range |

### Local storm reports

| status | when |
| --- | --- |
| `422` | `hours` outside 1 to 72, a `bbox` that is not four numbers, or an unknown category (`"unknown category: hial"`) |

### Tropical cyclones

| status | when |
| --- | --- |
| `404` | an unknown storm, or a storm NHC stopped advising on more than 30 days ago |
| `422` | `lat` or `lon` out of range on `/tropical/for-place` |

A storm with no model guidance yet is not an error: its `models` list is empty.

### Winter weather

| status | when |
| --- | --- |
| `422` | a `lat` or `lon` out of range, a `day` or `component` that is not one of the listed values, or a `threshold` that does not belong to the `kind` |

For a bad threshold the `detail` reads "threshold must be 4, 8 or 12 for snow,
or 0.01, 0.1 or 0.25 for ice".
