Error codes
Every error code, its meaning, and the fix.
The image editor reports two kinds of error codes: license codes, when the license check stops the editor, and AI codes, when an AI request fails. The reason codes are stable names. The sentences may change between versions.
License errors
When the license check stops the editor, onLicenseState reports state.status: 'blocked' with one of these reason codes, and the screen shows the message.
| Code | Meaning | Message | Fix |
|---|---|---|---|
missing-key | No key was given. | No licence key was given to the editor. Pass your key as the licenseKey prop. | Pass licenseKey. |
malformed | The value is not a license key. | This licence key was not recognised. | Copy the whole key again. |
unknown-key | The key was not signed by Layermetry, or it is a development key in a production build. | This licence key was not recognised. | Use a key from app.layermetry.com/licenses. |
bad-signature | The signature of the key does not match, or the value is not a license key. | This licence key was not recognised. | Copy the whole key again, without changes. |
legacy-key | The key has the format of an older version. | This licence key is in an older format that this editor no longer accepts. Generate a new key at app.layermetry.com/licenses. | Create a new key. |
expired | The expiry date has passed. | This licence key expired on (date). | Create a new key. See Expiry and renewal. |
not-yet-valid | The key starts in the future, usually because the device clock is wrong. | This licence key does not start until (date), which is in the future. Check this device's date and time. | Set the device clock automatically. |
wrong-domain | The key is not valid for the domain of the page. | This licence key is not valid for (host name). | Use a production key for this domain. |
revoked | The license server refused the key, for example because the license was cancelled. | The server's sentence, or "The licence server has rejected this key." | Check the license at app.layermetry.com/licenses. |
unconfirmed | The license could not be confirmed for the whole grace period, 30 days by default. | The editor has not been able to confirm its licence with Layermetry for (period). Check apiUrl, network rules and your key. | Allow requests to the license server. See Service outages. |
The screens for revoked and unconfirmed have a Try again button, which asks the license server again at once.
AI errors
Compare AIRequestError.code in your application. Messages can change. Hosted AI is coming soon and available only with an enterprise licence from Layermetry; the published error type retains service license codes.
| Code | Meaning | Retry guidance |
|---|---|---|
not-configured | AI has no usable configuration or available server model. | Configure an available operation before trying again. |
announced | The operation is not available in this release. | Wait for support. |
limit-reached | A session or host request limit was reached. | Retry after the limit is renewed or the input is reduced. |
invalid-input | A request violates the model schema or host restrictions. | Correct the input before trying again. |
no-provider | No provider serves the requested operation. | Configure a provider before trying again. |
transport-failed | A request function failed, an authenticated redirect was refused, or an endpoint returned an unknown failure. | Confirm whether the server accepted the work before resubmitting. |
invalid-response | The response was not readable JSON or its parser failed. | Check the response and server job before resubmitting. |
missing-license-key | The service received no SDK license key. | Correct the service setup before trying again. |
malformed-license-key | The service could not read the SDK license key. | Correct the service setup before trying again. |
invalid-license-key | The service refused the SDK license key. | Correct the service setup before trying again. |
license-unverifiable | The service could not verify the SDK license. | Retry after verification recovers. |
ai-quota-exceeded | The service request quota is exhausted. | Retry after the quota is renewed. |
unsupported-model | The server does not offer the requested model. | Choose an offered model before trying again. |
unsupported-provider | The server does not offer the requested provider. | Correct provider routing before trying again. |
store-unavailable | The server refused work because it could not record usage. | Retry after the usage store recovers. |
unknown-job | A job is absent, expired or inaccessible to this account. | Check the original job and account before starting new work. |
sign-in-required | The service requires a signed-in user. | Sign in before trying again. |
identity-mismatch | The signed-in account differs from the required account. | Use the correct account before trying again. |
identity-unverifiable | The service could not verify the signed-in user. | Retry after identity verification recovers. |
ai-credits-exhausted | The paying account has no AI credits. | Add credits before trying again. |
meter-off | The plan does not include this operation. | Use an eligible plan before trying again. |
invalid-config | A configuration or headers answer is unusable; no request was sent. | Correct configuration before trying again. |
invalid-output | A readable response is not a usable result for this operation. | Correct the response; another generation may incur a charge. |
auth-refused | The endpoint returned HTTP 401 or 403 without a known SDK code. | Correct authentication before trying again. |
rate-limited | The endpoint returned HTTP 429 without a known SDK code. | Retry after backoff when the server rejected submission. |
timeout | The configured submission timeout elapsed. | Check server acceptance before resubmitting. |
cancelled | The editor or user stopped the request. | Check whether accepted work is still running. |
outcome-unknown | A network failure left submission acceptance unknown. | Check the server before resubmitting. |
Provider errors
providerError preserves the server’s error alongside the SDK code.
| Field | Type | Description |
|---|---|---|
code | Optional string | The provider’s code, including codes the SDK does not recognize. |
message | Optional string | The provider’s plain-text explanation, limited to 500 characters. |
status | Optional number | The HTTP response status. |
requestId | Optional string | The request identifier from response headers or the body. |
Codes and request IDs are limited to 100 characters. Control characters are removed. Request IDs are read from x-request-id, x-correlation-id, or requestId in the body. Unknown provider codes do not replace the SDK’s code. Provider messages can repeat user content; avoid logging them when you only need a request ID.
Retry safety
A confirmed refusal can be retried after its cause is corrected. A response parsing failure does not prove generation was refused. outcome-unknown, timeout and cancellation during submission do not establish whether work was accepted or billed. Check server records before repeating those requests.
Automatic submission retries require an idempotency contract. They apply only to thrown network requests and HTTP 429, 502, 503 or 504. The server must recognize the reused key. See Retries.
errorMessages changes user-facing wording by category. onGenerationError receives the SDK error and attempt context. See Generation events.
Top-up address
With ai-credits-exhausted and meter-off, your server can send topUpUrl, the address where the account buys more credits. AIRequestError carries it as error.topUpUrl. The editor keeps only an http or https address, and it shows no link itself. You decide whether your users see a way to pay.
{ "error": { "code": "ai-credits-exhausted", "message": "This workspace has no AI credits left.", "topUpUrl": "https://app.example.com/billing" } }In your own code
The package exports AIRequestError and describeAIError, to show the same titles in your own interface:
import { AIRequestError, describeAIError } from '@layermetry/media-editor/react';
const error = new AIRequestError('limit-reached', 'You have made 20 pictures today. Try again tomorrow.', 429);
const { title, description } = describeAIError(error);
console.log(`${title}: ${description}`);
// Generation limit reached: You have made 20 pictures today. Try again tomorrow.