> Lettrove docs 1.x · https://docs.lettrove.com/docs/api/errors

# Error codes

Every refusal carries a stable **code**. Codes never change meaning within 1.x and new ones may be
added; messages may be reworded. Handle the code, show the message.

| Where | You get |
|---|---|
| In the page | `createEditor` rejects with a `LettroveEmbedError` (`error.code`, `error.message`, `error.docsUrl`); an open editor fires the `error` event |
| On your server | `@lettrove/node` throws a `LettroveApiError` (`code`, `message`, `status`, `requestId`, `retryAfter`, `docsUrl`) |
| Over HTTPS | JSON `{ "error": "…", "code": "…", "requestId": "…" }`, and `Retry-After` when rate-limited |

`docsUrl` links to the code's own row below, on the page for your major version
(`https://docs.lettrove.com/docs/1/api/errors#token_expired`). For what to check first by what you
see, read [Troubleshooting](/docs/going-live/troubleshooting).

| Code | Means | Do |
|---|---|---|
| `brand_not_found` | No brand, folder or part with that id is this person's or the project's | Check the id |
| `brand_read_only` | The brand is the project's: your users use it, only you change it | Change it on the project's brand page (Settings → Embed) |
| `call_timed_out` | The editor, or your provider, did not answer in time | Retry; check your network |
| `capability_missing` | The feature is not on for this project | Settings → Embed, or your plan |
| `design_conflict` | The design was saved elsewhere since it was opened | In the editor, your user chooses: the saved version, or theirs over it. Elsewhere, reopen it to get the newest |
| `design_invalid` | A design document is not one Lettrove made | Pass the `design` exactly as you got it |
| `design_not_found` | No design with that id belongs to this person | Check the `designId` and the user id |
| `design_too_new` | A newer major version of the editor saved it | Open it with that version |
| `editor_destroyed` | The editor was removed before the call answered | — |
| `feature_unsupported` | The editor release in the frame does not have this; the message names the release that added it | Follow a newer release |
| `frame_blocked` | The frame never answered | [Troubleshooting](/docs/going-live/troubleshooting#the-box-says-frame_blocked) |
| `image_not_hosted` | An image is not an `https://` address | Host the image |
| `image_unsupported` | A file is not PNG, JPEG, GIF, WebP or a safe SVG | Use one of those |
| `key_invalid` | A key is wrong, revoked, from a deleted project, or does not match the token's project | Check your keys |
| `message_too_large` | A design over 2 MB, or an image over 10 MB | Use smaller images; images are links, not content |
| `network_error` | `@lettrove/node` could not reach Lettrove, or it did not answer in time (status `0`) | Retry with backoff |
| `mode_unavailable` | The page asked for another mode than the project's | Remove `mode`, or use the right project |
| `options_invalid` | An option is wrong (test keys stop; live keys drop it) | The message names the option |
| `origin_not_allowed` | The site is not allowed, or the token is for another site | [Allowed sites](/docs/editor/allowed-sites) |
| `project_suspended` | The project is paused | Resume it in Settings → Embed |
| `protocol_mismatch` | Your loader and the editor share no protocol | Update `@lettrove/embed` |
| `provider_duplicate` | Two providers for one name. Not given in 1.x: `providers` is an object, so each name appears once | — |
| `provider_missing` | `storage` keeps a resource with you (`'host'`) but no provider for it was given | Give the provider, e.g. `'image:upload'` |
| `provider_not_host` | A provider was given for something Lettrove stores | Set `storage: { images: 'host' }` (or `designs: 'host'`), or remove the provider |
| `provider_failed` | Your provider threw, or answered something unusable; your message is shown | Check your provider |
| `quota_exceeded` | A plan limit was reached | Your plan, or wait for the next period |
| `rate_limited` | Too many requests for this key | Wait `Retry-After` seconds |
| `request_invalid` | A request body is not as documented; the message names the field | Fix the request |
| `service_unavailable` | Lettrove is briefly unavailable | Retry with backoff |
| `signature_invalid` | `verifyWebhook`: wrong secret, a changed body, or older than five minutes | Use the raw body and the current secret |
| `token_expired` | The token ran out | Renewed automatically through `getToken` |
| `token_invalid` | The token is missing, altered, or from before a key was revoked | Check your token route |
| `user_erased` | You asked to erase this person | — |
| `workspace_suspended` | Lettrove has suspended the embed for your workspace | support@lettrove.com |

Messages may be reworded between releases; codes never change meaning. Handle codes, show messages.
