# Errors

Source: https://docs.foodshot.ai/guides/errors

> What each error means, when to retry, and what to tell your vendor.

No error costs credits, and a failed generation is refunded automatically.

## Error format

```json
{
  "error": {
    "code": "invalid_request",
    "message": "The Idempotency-Key header is required. Send one unique value per photo, such as a UUID, and reuse it when you retry.",
    "param": "Idempotency-Key",
    "request_id": "req_9Tz3Kw7Qp2Lx5Nv8Bd4Hs6Jy"
  }
}
```

Build your logic on `code`. `message` is for developers: don't show it to vendors. `param` names the field at fault, and `request_id` helps us when you contact us.

## Request errors

These come back as the answer to your request, and no job is created.

| HTTP | Code                     | What it means                                                      | Retry?                   |
| ---- | ------------------------ | ------------------------------------------------------------------ | ------------------------ |
| 400  | `invalid_request`        | A field, parameter or header is missing or wrong; see `param`      | No, fix the request      |
| 400  | `style_not_available`    | The style doesn't exist or was retired                             | No, pick another style   |
| 400  | `image_unreadable`       | The photo file is damaged                                          | No                       |
| 400  | `image_too_small`        | The photo is under 512 px on its short side                        | No                       |
| 400  | `image_fetch_failed`     | We couldn't download your `image_url`                              | Yes, once the URL works  |
| 401  | `invalid_api_key`        | The key is missing, wrong or revoked                               | No                       |
| 402  | `insufficient_credits`   | Your live credits have run out                                     | After credits are added  |
| 403  | `permission_denied`      | Not allowed, for example a live key used from a browser            | No                       |
| 403  | `account_suspended`      | Your account is suspended                                          | No, contact us           |
| 404  | `not_found`              | No such generation, file or path                                   | No                       |
| 409  | `idempotency_conflict`   | This `Idempotency-Key` was used with a different body              | No                       |
| 413  | `image_too_large`        | The photo is over 20 MB or 100 megapixels                          | No                       |
| 413  | `payload_too_large`      | The request body is over 10 MB                                     | No, send `image_url`     |
| 415  | `unsupported_media_type` | The photo isn't JPEG, PNG, WebP or HEIC, or the body isn't JSON    | No                       |
| 429  | `rate_limited`           | Too many requests for this key                                     | Yes, after `Retry-After` |
| 429  | `queue_full`             | 500 jobs are already waiting                                       | Yes, after `Retry-After` |
| 429  | `daily_limit_reached`    | You reached today's job cap                                        | Yes, after 00:00 UTC     |
| 429  | `busy`                   | We are briefly busy                                                | Yes, after `Retry-After` |
| 500  | `internal_error`         | Something went wrong on our side                                   | Yes                      |
| 503  | `service_unavailable`    | We can't take the request right now, or your access isn't open yet | Yes, after `Retry-After` |

## Failed generations

A job that was accepted can still fail. You get `status: "failed"` and a `generation.failed` webhook, with one of these codes in `error.code`. The credit is refunded.

| Code                  | What it means                            | Retry?                            |
| --------------------- | ---------------------------------------- | --------------------------------- |
| `content_refused`     | The photo or the instruction was refused | Not with the same photo           |
| `image_unprocessable` | No result could be made from this photo  | Not with the same photo           |
| `generation_timeout`  | It took too long                         | Yes, with a new `Idempotency-Key` |
| `generation_failed`   | It failed for another reason             | Yes, with a new `Idempotency-Key` |
| `queue_timeout`       | It wasn't finished within 24 hours       | Yes, with a new `Idempotency-Key` |

## Retrying

* **Timeouts, network errors, `429` and `5xx`:** retry with the same `Idempotency-Key` and the same body. Wait for `Retry-After` when it is there; otherwise wait 1, 2, 4, 8 seconds and so on.
* **A failed generation:** create it again with a new `Idempotency-Key`.
* **Other `4xx` errors:** don't retry. Fix the request, or ask the vendor for another photo.
* **An error code you don't know:** we may add codes. Act on the HTTP status: retry `429` and `5xx`, and don't retry other `4xx`.

Some `429` and `5xx` answers come from our hosting platform without our JSON body. Retry them the same way.

## What to tell your vendor

| Code                     | Message for the vendor                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------- |
| `image_too_small`        | "This photo is too small. Please upload the original photo, not a screenshot."                          |
| `image_too_large`        | "This photo is too large. Please upload a smaller one."                                                 |
| `image_unreadable`       | "We couldn't open this photo. Please upload it again from your camera."                                 |
| `unsupported_media_type` | "Please upload a JPEG, PNG, WebP or HEIC photo."                                                        |
| `content_refused`        | "We couldn't use this photo. Please upload a photo that shows only the dish."                           |
| `image_unprocessable`    | "We couldn't create a picture from this photo. Please try a sharper, brighter photo of the whole dish." |
| `style_not_available`    | "This style is no longer available. Please choose another one."                                         |

Other codes need nothing from the vendor.
