# Error codes

Every code Formerie can send you, what it means, and what to do. Use your browser's find to jump to a code, such as
`FORM_CLOSED`. Not sure what's wrong yet? Start with [Troubleshooting](/guides/troubleshooting/), which begins from what you see.

## How to use this page

**Match on the code, not the message.** A `code` is stable, so your code can safely depend on it. A `message` can
change or be translated, so show it to people and don't test against it.

```json
{
  "ok": false,
  "error": {
    "code": "FORM_CLOSED",
    "message": "This form is no longer accepting submissions.",
    "requestId": "c1f4e0a2-7b1d-4a55-9d10-3f6a8e2b7c44"
  }
}
```

**Contacting us.** Most error responses include `error.requestId`, and the `X-Request-Id` response header can carry the
same value. When a request fails on our side, with a status of 500 or higher, the app shows it as **Reference**. Quote it
when you [write to us](https://formerie.com/contact/), since it lets us find that exact request.

**Reading an entry.** Each one gives the code, the HTTP status when there is one, what it means, when it happens, and
what to do. An entry with no status isn't an HTTP error. It's a value inside a response, such as a diagnostic or an
item in `issues`, and each section says where to find it.

## Submitting a form

What your page or server gets back when it loads, checks, or submits a public form. The server stops at the first check
that fails. [A submission was rejected](/guides/troubleshooting/#a-submission-was-rejected) has the order.

- `FORM_NOT_FOUND` (HTTP 404): There's no published form here that you can reach. **When:** the workspace or form handle is wrong, the form was never published, **Public access** is on **Unpublished**, a custom hostname isn't connected, or in the app the form isn't in this workspace. **Do:** Publish on the **Publish** tab, and copy the address from there.
- `FORM_DISABLED` (HTTP 403): The form is switched off. **When:** the form or its workspace isn't enabled. **Do:** Check the form and workspace in the app. If nothing there explains it, write to us.
- `FORM_NOT_OPEN` (HTTP 403): The form isn't taking responses yet. **When:** before its **Response window** opens. **Do:** Change the window on the **Publish** tab, or wait.
- `FORM_CLOSED` (HTTP 403): The form isn't taking responses anymore. **When:** **Public access** is on **Closed**, or the **Response window** has ended. **Do:** Change them on the **Publish** tab.
- `FORM_MAINTENANCE` (HTTP 503): The form is temporarily unavailable. **When:** **Public access** is on **Maintenance**. **Do:** Set it back to **Public**.
- `FORBIDDEN_ORIGIN` (HTTP 403): The request came from a site that isn't allowed. **When:** the `Origin` header isn't in the form's allowed origins, or an app request didn't come from the app. **Do:** See [A CORS or Origin error](/guides/troubleshooting/#a-cors-or-origin-error).
- `VALIDATION_FAILED` (HTTP 422): One or more answers or settings failed a check. **When:** a submission has bad answers, or a saved form has a bad setting. **Do:** Read `error.issues` and `error.fields`. Each item has a `path`, a `code`, and a `message`, listed below.
- `SPAM_REJECTED` (HTTP 403): A spam check caught the submission. **When:** the hidden field is filled in, it was sent too fast, or it holds too many links. **Do:** See [Rejected as spam](/guides/troubleshooting/#rejected-as-spam).
- `TURNSTILE_FAILED` (HTTP 403): Human verification failed, with any provider. **When:** the token is missing, used, or expired, or the keys or domain don't match. **Do:** See [Verification failed](/guides/troubleshooting/#verification-failed).
- `RATE_LIMITED` (HTTP 429): Too many requests in a short time. **When:** a form's **Submission limits** or a short-term limit on public routes was reached, or a verification or invitation email was resent too soon. **Do:** Wait, using `Retry-After` when it's sent, and keep the visitor's answers on screen.
- `FORM_QUOTA_REACHED` (HTTP 409): The form hit its limit of accepted submissions. **When:** it reached **Maximum accepted submissions**. **Do:** Raise or clear the limit under **Submission limits**, in **Settings**.
- `DUPLICATE_SUBMISSION` (HTTP 409): This submission was already accepted. **When:** a `metadata.idempotencyKey` is sent again. **Do:** Treat it as a success. Use a new key for each new submission.
- `QUEUE_FAILED` (HTTP 503): The email or retry couldn't be queued. **When:** a submission or a delivery retry couldn't be handed off for sending. **Do:** Try again shortly.

### Tests

These only ever answer a test. See [Test your form](/guides/test-your-form/).

- `TEST_LIMIT_REACHED` (HTTP 429): Nothing was stored, because this form or workspace reached its limit for tests. **When:** a test was sent past its daily limit, or past the number or size of tests a workspace can keep. **Do:** Delete tests in the app, or try again tomorrow. If real visitors could be seeing this, add their website to **Allowed websites**.
- `TEST_KEY_INVALID` (HTTP 401): Nothing was stored, and the submission didn't go out as a real one. **When:** the `X-Formerie-Test-Key` header holds a key that's wrong, revoked, expired, or for another form. **Do:** Create a new key on the form's **Tests** tab, or remove the header.
- `TEST_LINK_INVALID` (HTTP 410): Nothing was stored. **When:** a try link expired, was revoked, or its form is archived or in the trash. **Do:** Ask whoever shared it for a new link.
- `TEST_DRAFT_INVALID` (HTTP 409): Nothing was stored. **When:** the form's draft has a problem, so it can't be tried yet. **Do:** Fix what the form's **Publish** tab lists, then try again.
- `TEST_KEY_IGNORED_ORIGIN_LISTED`: A notice, not an error. The submission is real. **When:** a test key came from a website in **Allowed websites**, so the key was ignored. **Do:** Remove the key from that site's requests.
- `TEST_EMAIL_UNAVAILABLE` (HTTP 409): The test wasn't emailed. **When:** it has no email preview, or your login email isn't confirmed. **Do:** Confirm your email, or send a new test.
- `TEST_EMAIL_LIMIT`: The test was kept and not emailed. **When:** the link, key or account reached its daily limit for test emails. **Do:** Try again tomorrow.
- `TEST_EMAIL_NO_PREVIEW`: The test was kept and not emailed. **When:** its email couldn't be rendered when it arrived. **Do:** Check the form's template, then send a new test.
- `TEST_EMAIL_NO_VERIFIED_ADDRESS`: The test was kept and not emailed. **When:** the person it was for has no confirmed login email, or left the workspace. **Do:** Use **Send to me** on the entry.
- `TEST_EMAIL_QUEUE_FAILED`: The test was kept and not emailed. **When:** the email couldn't be queued. **Do:** Use **Send to me** on the entry.
- `TEST_EMAIL_SENDER_UNAVAILABLE`: The test was kept and not emailed. **When:** the form's sender isn't ready. **Do:** Finish the sender's setup, then use **Send to me**.
- `TEST_EMAIL_SEND_FAILED`: The test was kept and the email failed. **When:** the provider refused it, including after one retry. **Do:** Check the form's sender and provider, then use **Send to me**.

### Answers

These arrive in `error.issues` and `error.fields` of a `VALIDATION_FAILED`, one per problem. Show each `message` next to its
field. Your own validators return the `code` you gave them. [Form definition reference](/guides/form-reference/) has every option.

- `FIELD_REQUIRED`: A required answer is empty. **When:** the field is visible and `required`. **Do:** Ask for an answer. In your own UI, send the exact field name.
- `FIELD_TYPE_INVALID`: The answer has the wrong type. **When:** a number can't be read as a number, or a value isn't what the field holds. **Do:** Send the type the field expects.
- `FIELD_OBJECT_INVALID`: A group's answer isn't an object. **When:** a `group` field gets another value. **Do:** Send groups as nested objects.
- `FIELD_STRING_TOO_SHORT`, `FIELD_STRING_TOO_LONG`: The text's length is out of range. **When:** it's under `min` or over `max`. **Do:** Change the answer, or the limit.
- `FIELD_STRING_LENGTH_INVALID`: The text isn't the exact length. **When:** it doesn't match `exactLength`. **Do:** Change the answer, or the setting.
- `FIELD_STRING_PREFIX_INVALID`, `FIELD_STRING_SUFFIX_INVALID`: The text starts or ends the wrong way. **When:** it fails `startsWith` or `endsWith`. **Do:** Change the answer, or the setting.
- `FIELD_STRING_CONTAINS_REQUIRED`, `FIELD_STRING_CONTAINS_FORBIDDEN`: The text is missing required words, or holds refused ones. **When:** it fails `contains` or `notContains`. **Do:** Change the answer, or the setting.
- `FIELD_PATTERN_INVALID`: The text doesn't match the format. **When:** it fails `pattern`. **Do:** Change the answer, or the pattern.
- `FIELD_VALUE_NOT_ALLOWED`: The answer isn't one of the choices. **When:** it's not in `allowedValues`. **Do:** Send one of the listed values.
- `FIELD_EMAIL_INVALID`: Not an email address. **When:** an `email` answer fails the format check. **Do:** Ask for a valid address.
- `FIELD_PHONE_INVALID`: Not a phone number. **When:** it fails `phoneFormat`, such as `+15145550123`. **Do:** Ask for the full number.
- `FIELD_UUID_INVALID`: Not a UUID of the right version. **When:** it fails `uuidVersion`. **Do:** Send a valid UUID.
- `FIELD_COUNTRY_CODE_INVALID`: Not a country code. **When:** it fails `countryCode`. **Do:** Send a two-letter code.
- `FIELD_POSTAL_CODE_INVALID`: Not a postal code for that country. **When:** it fails `postalCodeCountry`. **Do:** Ask for a valid code.
- `FIELD_REGION_CODE_INVALID`: Not a region code for that country. **When:** it fails `regionCodeCountry`. **Do:** Ask for a valid code.
- `FIELD_URL_INVALID`: Not a web address. **When:** a `url` answer can't be read. **Do:** Ask for a full address.
- `FIELD_URL_PROTOCOL_NOT_ALLOWED`: The address uses a refused protocol. **When:** it's not in `allowedProtocols`. **Do:** Use an allowed one, such as `https`.
- `FIELD_DATE_INVALID`: Not a real date. **When:** a `date` answer can't be read. **Do:** Ask for a real date.
- `FIELD_DATE_TOO_EARLY`, `FIELD_DATE_TOO_LATE`: The date is out of range. **When:** it's before `dateMin` or after `dateMax`. **Do:** Change the date, or the range.
- `FIELD_TIME_INVALID`: Not a time in the right format. **When:** it fails `timeFormat`. **Do:** Send `HH:mm` or `HH:mm:ss`, as the field asks.
- `FIELD_DATETIME_INVALID`: Not a date and time in the right format. **When:** it fails `dateTimeFormat`. **Do:** Send ISO 8601 with a time zone.
- `FIELD_NUMBER_TOO_SMALL`, `FIELD_NUMBER_TOO_LARGE`: The number is out of range. **When:** it's under `min` or over `max`. **Do:** Change the answer, or the range.
- `FIELD_INTEGER_REQUIRED`: The number must be whole. **When:** `integer` is on. **Do:** Ask for a whole number.
- `FIELD_DECIMAL_PLACES_INVALID`: Too many decimals. **When:** it's over `maxDecimalPlaces`. **Do:** Round the answer, or raise the setting.
- `FIELD_ACCEPTED_REQUIRED`: A consent box wasn't accepted. **When:** `accepted` is on and the box isn't checked. **Do:** Ask the person to accept.
- `FIELD_SELECTION_TOO_FEW`, `FIELD_SELECTION_TOO_MANY`: The wrong number of options is selected. **When:** it's under `minSelections` or over `maxSelections`. **Do:** Change the selection, or the limits.
- `FIELD_ARRAY_TOO_SHORT`, `FIELD_ARRAY_TOO_LONG`: A list has the wrong number of items. **When:** it's under `minItems` or over `maxItems`. **Do:** Change the list, or the limits.
- `FIELD_ARRAY_DUPLICATES`: A list repeats an item. **When:** `uniqueItems` is on. **Do:** Remove the repeats.

## Saving a form

When a change to a form is refused, which you see in the app when it saves. The first code is the response's own. The others arrive in `error.issues` of a
`VALIDATION_FAILED`, each with a `path` to the setting. Fix those paths and save again.

- `CONFIG_VERSION_CONFLICT` (HTTP 409): The form or workspace changed since you loaded it. **When:** someone else saved first, or an older tab saves. **Do:** Reload, then make your change again.

### Any setting

- `FORM_CONFIG_UNKNOWN_KEY`: That key isn't a setting there. **When:** a key is misspelled or in the wrong place. **Do:** Use the key in `suggestion` when there is one, or remove it.
- `FORM_CONFIG_OBJECT_REQUIRED`, `FORM_CONFIG_ARRAY_REQUIRED`, `FORM_CONFIG_STRING_REQUIRED`, `FORM_CONFIG_STRING_ARRAY_REQUIRED`, `FORM_CONFIG_STRING_MAP_REQUIRED`, `FORM_CONFIG_BOOLEAN_REQUIRED`, `FORM_CONFIG_NUMBER_REQUIRED`, `FORM_CONFIG_INTEGER_REQUIRED`: A setting has the wrong type. **When:** the value at `path` isn't what the name says, such as an object or a whole number. **Do:** Send that type.
- `FORM_CONFIG_ARRAY_TOO_SHORT`, `FORM_CONFIG_ARRAY_TOO_LONG`: A list has too few or too many entries. **When:** it's outside the bounds in `message`. **Do:** Add or remove entries.
- `FORM_CONFIG_STRING_TOO_LONG`: A text setting is too long. **When:** it's over the length in `message`. **Do:** Shorten it.
- `FORM_CONFIG_NUMBER_TOO_SMALL`: A number is below its minimum. **When:** it's under the value in `message`. **Do:** Raise it.
- `FORM_CONFIG_RANGE_INVALID`: A minimum is above its maximum. **When:** a pair such as `min` and `max` is reversed. **Do:** Swap or fix them.
- `FORM_CONFIG_ENUM_INVALID`: The value isn't one of the options. **When:** it's not in the list in `message`. **Do:** Use a listed value.
- `FORM_CONFIG_ID_DUPLICATE`: Two entries share an `id`. **When:** a list repeats one. **Do:** Give each entry its own.
- `FORM_CONFIG_CODE_INVALID`: A custom `code` is badly formed. **When:** it has anything but capitals, digits, and `_`. **Do:** Use a code like `CUSTOM_POSTAL_CODE`.
- `FORM_CONFIG_FIELD_PATH_INVALID`: A field path is badly formed. **When:** it doesn't use dots and brackets. **Do:** Write it like `contact.email`.
- `FORM_CONFIG_URL_INVALID`, `FORM_CONFIG_URL_PROTOCOL_INVALID`: A web address setting is invalid. **When:** it can't be read, or doesn't use an allowed protocol. **Do:** Use a full `https` address.
- `FORM_CONFIG_EMAIL_INVALID`: An email setting is invalid. **When:** it isn't an address. **Do:** Fix the address.
- `FORM_CONFIG_DATE_INVALID`, `FORM_CONFIG_DATETIME_INVALID`: A date setting is invalid. **When:** a date isn't a real `YYYY-MM-DD`, or a date and time has no time zone. **Do:** Fix the format.
- `FORM_CONFIG_COLOR_INVALID`: A color is invalid. **When:** it isn't a `#RRGGBB` value. **Do:** Use that format.
- `FORM_CONFIG_CSS_LENGTH_INVALID`: A size is invalid. **When:** it isn't a safe length. **Do:** Use a value like `44rem`, `720px`, `90%`, or `72ch`.
- `FORM_CONFIG_LANGUAGE_INVALID`: The language is invalid. **When:** it isn't a language tag. **Do:** Use one like `en-CA` or `fr-CA`.
- `FORM_CONFIG_MESSAGES_INVALID`: A message list is invalid. **When:** it isn't an object of text values. **Do:** Send text for each one.

### Fields

- `FORM_CONFIG_FIELDS_REQUIRED`: The form has no fields. **When:** the list is empty. **Do:** Add a field.
- `FORM_CONFIG_FIELD_INVALID`: A field isn't an object. **When:** an entry under `fields` is another value. **Do:** Send an object with a `type`.
- `FORM_CONFIG_FIELD_TYPE_INVALID`: The field type doesn't exist. **When:** `type` isn't one of the twelve. **Do:** See [Form definition reference](/guides/form-reference/).
- `FORM_CONFIG_TOO_MANY_FIELDS`, `FORM_CONFIG_NESTING_TOO_DEEP`: The form is too big. **When:** it has too many fields or nested levels. **Do:** Simplify it. The limit is in `message`.
- `FORM_CONFIG_FIELD_OPTION_INVALID`: That option doesn't work here. **When:** it doesn't apply to this field type or has a bad value. **Do:** Read `message`, then remove or fix it.
- `FORM_CONFIG_FIELD_OPTION_CONFLICT`: Two options can't be used together. **When:** such as `exactLength` with `min`. **Do:** Keep one.
- `FORM_CONFIG_DEFAULT_VALUE_INVALID`, `FORM_CONFIG_DEFAULT_VALUE_NOT_ALLOWED`: `defaultValue` doesn't fit. **When:** it has the wrong type, or isn't in `allowedValues`. **Do:** Change it.
- `FORM_CONFIG_COUNTRY_CODE_INVALID`, `FORM_CONFIG_COUNTRY_UNSUPPORTED`: A country setting is invalid. **When:** `countryCode` isn't `iso2`, or a postal or region check isn't `CA` or `US`. **Do:** Use those values.
- `FORM_CONFIG_PHONE_FORMAT_INVALID`, `FORM_CONFIG_UUID_VERSION_INVALID`, `FORM_CONFIG_TIME_FORMAT_INVALID`, `FORM_CONFIG_DATETIME_FORMAT_INVALID`: A format setting is invalid. **When:** it isn't `e164`, `any`, `v4`, `v7`, `HH:mm`, `HH:mm:ss`, or `iso8601`, as that setting allows. **Do:** Use one of those.
- `FORM_CONFIG_URL_PROTOCOL_UNSAFE`: A protocol isn't safe. **When:** `allowedProtocols` holds one that's refused as unsafe. **Do:** Remove it.
- `FORM_CONFIG_REGEX_PATTERN_INVALID`, `FORM_CONFIG_REGEX_PATTERN_TOO_LONG`, `FORM_CONFIG_REGEX_FLAGS_INVALID`: A regular expression is refused. **When:** it doesn't compile, is too long, or has flags other than `i`, `m`, and `u`. **Do:** Fix it.
- `FORM_CONFIG_PROCESSOR_REQUIRED`, `FORM_CONFIG_PIPELINE_STEP_INVALID`, `FORM_CONFIG_TOO_MANY_PROCESSORS`: A field's pipeline is invalid. **When:** it's empty, has too many steps, or a step isn't a sanitizer, validator, or transformer. **Do:** Fix the steps.
- `FORM_CONFIG_SANITIZER_TYPE_INVALID`, `FORM_CONFIG_TRANSFORMER_TYPE_INVALID`, `FORM_CONFIG_CASE_TRANSFORM_INVALID`, `FORM_CONFIG_TOO_MANY_MAP_ENTRIES`: A sanitizer or transformer is refused. **When:** the type doesn't exist, the case isn't `upper` or `lower`, or a map is too long. **Do:** See [Form definition reference](/guides/form-reference/).

### Validators and conditions

- `FORM_CONFIG_VALIDATOR_INVALID`: The validator `type` doesn't exist. **When:** it's misspelled or unsupported. **Do:** Use a listed type.
- `FORM_CONFIG_VALIDATOR_REQUIRED`: A rule has nothing to check. **When:** an action has no `validator` or `validatorRef`. **Do:** Add one.
- `FORM_CONFIG_VALIDATOR_REF_UNKNOWN`: A `validatorRef` points to nothing. **When:** no preset has that name. **Do:** Fix the name.
- `FORM_CONFIG_VALIDATOR_TOO_DEEP`, `FORM_CONFIG_TOO_MANY_VALIDATORS`, `FORM_CONFIG_TOO_MANY_RULES`: Rules are too big. **When:** they're nested too deeply, or there are too many. **Do:** Simplify them. The limit is in `message`.
- `FORM_CONFIG_RULE_ID_DUPLICATE`: Two validation rules share an ID. **When:** an `id` repeats. **Do:** Change one.
- `FORM_CONFIG_FIELD_REF_UNKNOWN`: A path names a field that doesn't exist. **When:** a field was renamed or removed. **Do:** Fix the path.
- `FORM_CONFIG_FIELD_REF_NOT_SCALAR`, `FORM_CONFIG_FIELD_REF_TYPE_INVALID`: A path names the wrong kind of field. **When:** it points to a group, or to a type this setting can't use. **Do:** Point to a suitable field.
- `FORM_CONFIG_CONDITION_OPERATOR_INVALID`: The condition `operator` doesn't exist. **When:** it's misspelled or unsupported. **Do:** See [Conditions](/guides/form-reference/#conditions).
- `FORM_CONFIG_CONDITION_REQUIRED`: A condition group is empty. **When:** it has no conditions. **Do:** Add one, or remove the group.
- `FORM_CONFIG_CONDITION_TOO_DEEP`, `FORM_CONFIG_TOO_MANY_CONDITIONS`, `FORM_CONFIG_TOO_MANY_NAMED_CONDITIONS`, `FORM_CONFIG_NAMED_CONDITION_TOO_LONG`: Conditions are too big. **When:** they're nested too deeply, too many, or too long. **Do:** Simplify them. The limit is in `message`.
- `FORM_CONFIG_VISIBILITY_RULE_ID_DUPLICATE`, `FORM_CONFIG_VISIBILITY_RULE_PATH_DUPLICATE`: Visibility rules overlap. **When:** two share an ID, or target the same field. **Do:** Keep one per field.
- `FORM_CONFIG_VISIBILITY_STATE_INVALID`: The visibility state is invalid. **When:** it isn't `visible` or `hidden`. **Do:** Use one of those.

### Steps and content

- `FORM_CONFIG_TOO_MANY_STEPS`, `FORM_CONFIG_STEP_SUMMARY_TOO_LONG`: Steps are too big. **When:** there are too many, or a summary is too long. **Do:** Shorten them. The limit is in `message`.
- `FORM_CONFIG_STEP_VALIDATE_ON_INVALID`: `validateOn` is invalid. **When:** it isn't `change`, `blur`, or `stepSubmit`. **Do:** Use one of those.
- `FORM_CONFIG_CONTENT_BLOCK_TYPE_INVALID`: The content block type doesn't exist. **When:** it isn't `text` or `separator`. **Do:** Use one of those.
- `FORM_CONFIG_CONTENT_BLOCK_POSITION_CONFLICT`: A block has two positions. **When:** it's set both before and after a field. **Do:** Keep one.
- `FORM_CONFIG_TOO_MANY_CONTENT_BLOCKS`, `FORM_CONFIG_CONTENT_BLOCK_TOO_LONG`: Content blocks are too big. **When:** there are too many, or one is too long. **Do:** Shorten them. The limit is in `message`.

### Limits, origins, and address

- `TEST_ORIGIN_NOT_ALLOWED` (HTTP 409): The test website wasn't saved. **When:** it's already an allowed website or the form's own address, so its submissions are real. **Do:** Remove it from **Allowed websites** first if you meant to move it.
- `TEST_ORIGIN_HAS_REAL_SUBMISSIONS` (HTTP 409): The test website wasn't saved yet. **When:** real submissions came from it in the last 30 days. **Do:** Check that it isn't your live site, then confirm. Its submissions will reach nobody.
- `FORM_CONFIG_RATE_LIMIT_TOO_HIGH`: A rate limit is above its upper bound. **When:** a `rateLimits` window or `max` is too high. **Do:** Lower it. See [Spam and limits](/guides/spam-protection/).
- `FORM_CONFIG_LIMIT_SCOPE_INVALID`, `FORM_CONFIG_QUOTA_PERIOD_INVALID`: A limit setting is invalid. **When:** the rate limit or quota scope, or the quota period, doesn't exist. **Do:** Use a listed value.
- `FORM_CONFIG_ORIGIN_INVALID`: An allowed origin is invalid. **When:** it has a path, is empty, or isn't `http` or `https`. **Do:** Use only the address, like `https://example.com`.
- `FORM_CONFIG_ORIGIN_WILDCARD`: An allowed origin uses a wildcard. **When:** it holds `*`. **Do:** List each address.
- `FORM_CONFIG_PRIMARY_PUBLIC_TARGET_KIND_INVALID`, `FORM_CONFIG_PRIMARY_PUBLIC_TARGET_BINDING_INVALID`, `FORM_CONFIG_PRIMARY_PUBLIC_TARGET_HOSTNAME_INVALID`: The public address setting is invalid. **When:** a kind, binding, or hostname isn't a valid value. **Do:** Choose the address again on the **Publish** tab.
- `FORM_CONFIG_PRIMARY_PUBLIC_TARGET_HOSTNAME_NOT_FOUND`: That hostname isn't in this workspace. **When:** it was removed, or belongs elsewhere. **Do:** Choose one under **Domains**.
- `FORM_CONFIG_PRIMARY_PUBLIC_TARGET_HOSTNAME_NOT_READY`: That hostname isn't ready. **When:** it isn't verified and enabled. **Do:** Finish its setup under **Domains**.
- `FORM_CONFIG_PRIMARY_PUBLIC_TARGET_BINDING_MISMATCH`: The hostname is connected differently. **When:** its connection to a workspace or a form doesn't match. **Do:** Check its connection under **Domains**.

### Human verification

- `FORM_CONFIG_VERIFICATION_PROVIDER_INVALID`, `FORM_CONFIG_VERIFICATION_MODE_INVALID`: The verification choice is invalid. **When:** the provider doesn't exist, the mode isn't `managed` or `custom`, or managed mode isn't used with Turnstile. **Do:** Choose again under **Human verification**.
- `FORM_CONFIG_SITE_KEY_REQUIRED`, `FORM_CONFIG_SITE_KEY_INVALID`: The site key is missing or invalid. **When:** verification is on with your own keys. **Do:** Paste the site key from your provider.
- `FORM_CONFIG_VERIFICATION_SECRET_REQUIRED`: The secret key is missing. **When:** custom verification is on. **Do:** Paste the secret key from your provider.
- `FORM_CONFIG_VERIFICATION_SECRET_PLAINTEXT`: A secret isn't encrypted. **When:** a definition holds it as plain text. **Do:** Enter it under **Human verification**, which encrypts it.
- `FORM_CONFIG_VERIFICATION_SECRET_ENCRYPTION_UNAVAILABLE`: The secret key couldn't be encrypted. **When:** something is wrong on our side. **Do:** Write to us.
- `FORM_CONFIG_SCORE_INVALID`: **Minimum score** is invalid. **When:** it isn't between 0 and 1. **Do:** Pick a value in that range.

### Delivery settings

The app writes these settings for you from the **Delivery** tab and **Destinations**, and the form update doesn't accept them. So
you'd only see them if a stored form holds a bad value.

- `FORM_CONFIG_PROVIDER_INVALID`, `FORM_CONFIG_PROVIDER_DUPLICATE`, `FORM_CONFIG_PROVIDER_ACCESS_INVALID`, `FORM_CONFIG_SECRET_REF_INVALID`, `FORM_CONFIG_PROVIDER_RECIPIENTS_UNSUPPORTED`: The form's email provider settings are invalid. **When:** a provider isn't supported or is repeated, its access settings are wrong, or it can't send to these recipients. **Do:** Review **Destinations**, then save the **Delivery** tab again.
- `FORM_CONFIG_FALLBACK_TRIGGER_INVALID`, `FORM_CONFIG_FIELD_POLICY_EMPTY`, `FORM_CONFIG_TOO_MANY_FALLBACK_PROVIDERS`: The fallback provider settings are invalid. **When:** a trigger isn't supported, a field policy is empty, or there are too many. **Do:** Save the **Delivery** tab again, or write to us.
- `FORM_CONFIG_SMTP_HOST_REQUIRED`, `FORM_CONFIG_SMTP_HOST_INVALID`, `FORM_CONFIG_SMTP_PORT_REQUIRED`, `FORM_CONFIG_SMTP_PORT_INVALID`, `FORM_CONFIG_SMTP_SECURITY_REQUIRED`, `FORM_CONFIG_SMTP_SECURITY_INVALID`, `FORM_CONFIG_SMTP_USERNAME_REQUIRED`, `FORM_CONFIG_SMTP_PASSWORD_SECRET_REQUIRED`: An SMTP setting is missing or invalid. **When:** the host isn't a hostname, the port isn't 465, 587, or 2525, the security doesn't suit the port, or a credential is missing. **Do:** Reconnect the provider under **Destinations**.
- `FORM_CONFIG_MAILGUN_DOMAIN_REQUIRED`, `FORM_CONFIG_MAILGUN_DOMAIN_INVALID`, `FORM_CONFIG_MAILGUN_REGION_INVALID`: A Mailgun setting is missing or invalid. **When:** the sending domain isn't a hostname, or the region isn't `us` or `eu`. **Do:** Reconnect the provider under **Destinations**.
- `FORM_CONFIG_DELIVERY_RULE_EMPTY`, `FORM_CONFIG_DELIVERY_RULE_ID_DUPLICATE`, `FORM_CONFIG_DELIVERY_RULE_RECIPIENTS_EMPTY`, `FORM_CONFIG_DELIVERY_RULE_TEMPLATES_EMPTY`, `FORM_CONFIG_TOO_MANY_DELIVERY_RULES`: A delivery rule is invalid. **When:** it changes nothing, repeats an ID, has an empty list, or there are too many. **Do:** Review the rules on the **Delivery** tab.
- `FORM_CONFIG_TEMPLATE_INVALID`, `FORM_CONFIG_EMAIL_TEMPLATE_HTML_UNSAFE`: The form's email template is refused. **When:** it can't be read, or its HTML isn't safe to send. **Do:** See [Notification Templates](/guides/notification-templates/).

## Publishing

What can stop a form going live, and what the **Publish** tab warns you about. Blockers and warnings arrive with a `code`, a
`message`, and often a `fix`, under **Delivery readiness**.

### Refused

- `FORM_DELIVERY_NOT_READY` (HTTP 409): The form has blockers. **When:** you publish while the items below remain. **Do:** Clear what **Delivery readiness** lists.
- `FORM_NOT_PUBLISHED` (HTTP 409): There's no published version yet. **When:** you set **Public access** before the first publish. **Do:** Publish first.

### Blockers

- `FORM_CONFIG_CHOICES_REQUIRED`: A question has no choices, so nobody can answer it. **When:** a choice field has no `allowedValues`. **Do:** List the choices.
- `FORM_CONFIG_CHOICE_BLANK`, `FORM_CONFIG_CHOICE_DUPLICATE`: A choice is blank, or listed twice. **When:** `allowedValues` holds one. **Do:** Fix the list.
- `FORM_CONFIG_STEP_FIELD_DUPLICATE`: A field is in more than one step. **When:** two steps list it. **Do:** Keep it in one.
- `FORM_DELIVERY_SENDER_NOT_READY`: The chosen sender can't send. **When:** it isn't verified or active. **Do:** Confirm it under **Senders**, or choose another.
- `FORM_DELIVERY_RECIPIENTS_NOT_READY`: No recipient can receive email. **When:** none of the form's recipients is usable. **Do:** Have one confirm by email, or add another under **Delivery**.
- `FORM_CONFIG_VERIFICATION_SECRET_MISSING`: Human verification has no secret key. **When:** custom verification is on with no stored key, or managed keys aren't available. **Do:** Enter the key under **Human verification**. For managed keys, write to us.
- `FORM_CONFIG_VERIFICATION_SITE_KEY_MISSING`, `FORM_CONFIG_VERIFICATION_SECRET_KEY_UNAVAILABLE`, `FORM_CONFIG_PROVIDER_BINDING_MISSING`, `FORM_CONFIG_PROVIDER_SECRET_MISSING`: Something this form needs isn't available on our side. **When:** a managed key, an encryption key, or a provider's access can't be found. **Do:** Reconnect the provider under **Destinations**, if you use one. Otherwise write to us.

### Warnings and advice

None of these stops you from publishing.

- `FORM_DELIVERY_STORE_ONLY`: Responses will be kept but not emailed. **When:** the form has no recipients. **Do:** Add one under **Delivery** if you want email.
- `FORM_DELIVERY_RECIPIENTS_PARTIALLY_BLOCKED`: Some recipients can't receive email. **When:** at least one is usable and others aren't. **Do:** Have them confirm, or re-enable them.
- `FORM_DELIVERY_TEST_NOT_SENT`: You haven't sent a test yet. **When:** delivery is set up with no test. **Do:** Choose **Send delivery test**.
- `FORM_DELIVERY_TEST_STALE`: Delivery settings changed after the last test. **When:** you changed them since. **Do:** Send another test.
- `FORM_DELIVERY_TEST_FAILED`: The last test didn't succeed. **When:** the latest test failed. **Do:** Fix the cause, then test again.
- `FORM_DEFINITION_UNKNOWN_KEYS`: The form holds settings that do nothing. **When:** usually it's from before these keys were refused. **Do:** Save that section again without them.
- `FORM_PUBLISH_ORIGINS_MISSING`: No website address is listed. **When:** you choose **API-only** with no allowed origins, so browsers would refuse your site's requests. **Do:** Add it under **Your website addresses**.

### Setup checklist

The workspace's setup steps can return these as their `code`.

- `SETUP_NO_FORM`, `SETUP_FORM_HAS_NO_FIELDS`: There's no form to work with yet. **When:** the workspace has no form, or it has no fields. **Do:** Create the form, and add a field.
- `SETUP_NOT_PUBLISHED`, `SETUP_UNPUBLISHED_CHANGES`: The form isn't live, or its latest changes aren't. **When:** it was never published, or the draft has moved on. **Do:** Publish on the **Publish** tab.
- `SETUP_NO_RESPONSES`: No response has come in yet. **When:** the form is new. **Do:** Send yourself a test response.

## Delivery

Each row under **Deliveries** has a **diagnostic** code, and may also have the raw **error code** from the attempt. See
[My email didn't arrive](/guides/troubleshooting/#my-email-didnt-arrive).

### Diagnostics

- `DELIVERY_QUEUED`, `DELIVERY_WAITING_FOR_ATTEMPT`: Delivery is waiting for an attempt. **When:** it hasn't run yet. **Do:** Nothing yet.
- `DELIVERY_ATTEMPT_RECORDED`: An attempt is on record, with its status from the provider. **When:** the row has no more specific diagnostic. **Do:** Nothing unless the status says it failed.
- `DELIVERY_ACCEPTED`, `DELIVERY_COMPLETED`: The provider accepted the email. **When:** the attempt succeeded. **Do:** If it hasn't arrived, see [Delivered, but not in the inbox](/guides/troubleshooting/#delivered-but-not-in-the-inbox).
- `DELIVERY_PROVIDER_UNREACHABLE_RETRYING`, `DELIVERY_PROVIDER_TEMPORARY_ERROR`: A temporary problem with the provider. **When:** an attempt failed and another will run. **Do:** Nothing yet. Formerie will try again.
- `DELIVERY_STALLED`: Delivery stopped retrying after a temporary error. **When:** its attempts didn't finish. **Do:** Open the response and retry.
- `DELIVERY_RECIPIENTS_UNAVAILABLE`: No active, verified recipient. **When:** none can receive this response. **Do:** Have the recipient confirm by email, or add another under **Delivery**.
- `DELIVERY_SENDER_UNAVAILABLE`: The chosen sender isn't active or verified. **When:** at sending time. **Do:** Confirm it under **Senders**, or set **Send from** back to the Formerie default.
- `DELIVERY_CREDENTIALS_MISSING`: The provider is missing its credentials. **When:** its key or password isn't available. **Do:** Reconnect it under **Destinations**.
- `DELIVERY_PROVIDER_NOT_FOUND`: The configured provider couldn't be used. **When:** it was removed or isn't available. **Do:** Review **Destinations** and the **Delivery** tab.
- `DELIVERY_PROVIDER_UNREACHABLE`: The provider couldn't be reached. **When:** the final attempt had a network failure. **Do:** Check the provider's status, then retry.
- `DELIVERY_PROVIDER_ERROR`: The provider didn't accept the email. **When:** it refused the final attempt. **Do:** Check its status and your settings with it, then retry.
- `DELIVERY_FAILED`: Delivery failed before the provider accepted it. **When:** no more specific diagnostic applies. **Do:** Review the sender, recipients, and provider, then retry.

### Raw error codes

The same failures, as the attempt recorded them. Fix them the way the diagnostic says.

- `EMAIL_RECIPIENTS_UNAVAILABLE`, `EMAIL_SENDER_UNAVAILABLE`, `EMAIL_PROVIDER_NOT_FOUND`: Shown with the matching `DELIVERY_` diagnostic above. **When:** recipients, the sender, or the provider weren't usable at sending time. **Do:** See that diagnostic.
- `RESEND_API_KEY_MISSING`, `SENDGRID_API_KEY_MISSING`, `MAILGUN_API_KEY_MISSING`, `POSTMARK_TOKEN_MISSING`, `BREVO_API_KEY_MISSING`, `MAILTRAP_API_KEY_MISSING`, `MANDRILL_API_KEY_MISSING`, `SENDER_API_KEY_MISSING`, `SMTP2GO_API_KEY_MISSING`: That provider's key is missing. **When:** the attempt couldn't find it. **Do:** Reconnect the provider under **Destinations**.
- `RESEND_NETWORK_ERROR`, `SENDGRID_NETWORK_ERROR`, `MAILGUN_NETWORK_ERROR`, `POSTMARK_NETWORK_ERROR`, `BREVO_NETWORK_ERROR`, `MAILTRAP_NETWORK_ERROR`, `MANDRILL_NETWORK_ERROR`, `SENDER_NETWORK_ERROR`, `SMTP2GO_NETWORK_ERROR`, `SMTP_NETWORK_ERROR`: That provider couldn't be reached. **When:** the request failed on the network. **Do:** Check the provider's status. Formerie retries temporary failures.
- `RESEND_SEND_FAILED`, `SENDGRID_SEND_FAILED`, `MAILGUN_SEND_FAILED`, `POSTMARK_SEND_FAILED`, `BREVO_SEND_FAILED`, `MAILTRAP_SEND_FAILED`, `MANDRILL_SEND_FAILED`, `SENDER_SEND_FAILED`, `SMTP2GO_SEND_FAILED`, `SMTP_SEND_FAILED`, `CLOUDFLARE_EMAIL_SEND_FAILED`: The email service refused the email. **When:** it answered with an error. **Do:** Check the service's status and your settings with it, then retry. For the Formerie default address, write to us if it repeats.
- `CLOUDFLARE_EMAIL_BINDING_NOT_CONFIGURED`: The Formerie default email service isn't available. **When:** something is wrong on our side. **Do:** Write to us.
- `E_RATE_LIMIT_EXCEEDED`, `E_DELIVERY_FAILED`, `E_INTERNAL_SERVER_ERROR`: The Formerie default email service had a temporary problem. **When:** it reports one of these, or another code starting with `E_`. **Do:** Nothing yet for these three, since Formerie tries again. Write to us if it repeats.
- `MAILGUN_DOMAIN_MISSING`, `MAILGUN_REGION_INVALID`: A Mailgun setting is missing or invalid at sending time. **When:** the sending domain or region can't be used. **Do:** Reconnect the provider under **Destinations**.
- `SENDER_UNSUPPORTED_MESSAGE`: Sender.net can't send this email. **When:** the message has more than this provider supports, such as several recipients. **Do:** Use one primary recipient, or another provider.
- `SMTP_HOST_MISSING`, `SMTP_PORT_INVALID`, `SMTP_SECURITY_INVALID`, `SMTP_USERNAME_MISSING`, `SMTP_PASSWORD_MISSING`: An SMTP setting is missing or invalid. **When:** the attempt can't connect without it. **Do:** Reconnect the provider under **Destinations**.
- `SMTP_GREETING_FAILED`, `SMTP_EHLO_FAILED`, `SMTP_STARTTLS_UNAVAILABLE`, `SMTP_STARTTLS_FAILED`, `SMTP_AUTH_FAILED`: The SMTP server refused the connection or the login. **When:** at that step of the exchange. **Do:** Check the host, port, security, and credentials with your provider.
- `SMTP_MAIL_FROM_FAILED`, `SMTP_RCPT_TO_FAILED`, `SMTP_DATA_FAILED`: The SMTP server refused the sender, a recipient, or the message. **When:** at that step of the exchange. **Do:** Check that your provider allows this sender and recipient.

### Retrying

- `DELIVERY_NOT_RETRYABLE` (HTTP 409): This delivery can't be retried now. **When:** only a failed or stuck delivery can be, so one that's already delivered can't. **Do:** Nothing, unless it failed for another reason.
- `DELIVERY_ATTEMPT_IN_PROGRESS` (HTTP 409): An attempt is running. **When:** you retry during one. **Do:** Wait for its result.

### Test emails

- `FORM_DELIVERY_TEST_NOT_READY` (HTTP 409): The form can't send a test yet. **When:** a sender or recipient isn't ready, or there are no recipients. **Do:** Follow **Delivery readiness**.
- `FORM_DELIVERY_TEST_NO_RECIPIENTS` (HTTP 409): The sample answers match no recipient. **When:** recipient conditions exclude them all. **Do:** Change the sample answers under **Preview**, or review the conditions.
- `FORM_DELIVERY_TEST_RATE_LIMITED` (HTTP 429): Tests are sent too fast. **When:** you send more than one a minute. **Do:** Wait a minute.
- `FORM_DELIVERY_TEST_PAYLOAD_TOO_LARGE` (HTTP 413): The sample answers are too big. **When:** they're over 64 KB. **Do:** Shorten them.
- `FORM_DELIVERY_TEST_SEND_FAILED` (HTTP 502): The provider couldn't confirm the test. **When:** it refused the email or didn't answer. **Do:** Check the sender and provider, and whether the recipient got it, then try again.
- `FORM_DELIVERY_TEST_RESULT_NOT_RECORDED` (HTTP 500): The test's result couldn't be saved. **When:** something failed on our side. **Do:** Check the recipient's inbox, then try again.

## Signing in

Your account, your sign-in methods, and your session.

- `UNAUTHORIZED` (HTTP 401): You aren't signed in, or the credentials didn't work. **When:** a session expired, a password, link, or passkey is wrong or expired. **Do:** Sign in again, or request a new link.
- `AUTH_RATE_LIMITED` (HTTP 429): Too many attempts or account changes. **When:** in a short time. **Do:** Wait for the time in `message`.
- `AUTH_RECENT_AUTH_REQUIRED` (HTTP 403): This change needs a fresh sign-in. **When:** you change something sensitive long after signing in. **Do:** Sign in again, then repeat it.
- `AUTH_SIGNUP_PASSWORD_REQUIRED` (HTTP 409): This signup set a password. **When:** you confirm the email link without it. **Do:** Enter the password chosen at signup, or continue without one.
- `AUTH_SIGNUP_PASSWORD_INCORRECT` (HTTP 401): That isn't the password chosen at signup. **When:** you confirm the email link with another one. **Do:** Enter the right one, or continue without a password.
- `AUTH_EMAIL_IN_USE` (HTTP 409): Another account uses this email. **When:** you change your address to it. **Do:** Use another address, or sign in to that account.
- `AUTH_IDENTITY_NOT_FOUND` (HTTP 404): That sign-in method isn't connected. **When:** you remove a password, passkey, or provider you don't have. **Do:** Reload **Sign-In & Security**.
- `AUTH_LAST_ACCESS_METHOD` (HTTP 409): This is your only way to sign in. **When:** you remove your last password, passkey, or provider. **Do:** Add another one first.
- `AUTH_ACCOUNT_DELETE_BLOCKED` (HTTP 409): Your account still owns things that need a decision. **When:** you delete an account with workspaces or forms to settle. **Do:** Resolve the ones listed. See [Delete your data](/guides/delete-your-data/).
- `AUTH_MFA_INVALID` (HTTP 401): The authenticator or recovery code is wrong. **When:** at sign-in or a security change. **Do:** Enter a current code.
- `AUTH_MFA_NOT_ENABLED` (HTTP 409): Authenticator verification isn't on. **When:** you use a code without it. **Do:** Turn it on first.
- `AUTH_MFA_SETUP_REQUIRED` (HTTP 404): The authenticator setup wasn't found. **When:** you confirm a setup that was never started or has expired. **Do:** Start again.
- `AUTH_MFA_CURRENT_FACTOR_REQUIRED` (HTTP 403): Replacing your authenticator needs proof. **When:** you set up a new one. **Do:** Enter a code from the current app, or a recovery code.
- `AUTH_MFA_SECRET_UNAVAILABLE` (HTTP 500): Authenticator verification is temporarily unavailable. **When:** something is wrong on our side. **Do:** Try again later, and write to us with the **Reference** if it repeats.

### Sign-in with a provider

After Google, Apple, or GitHub, you come back to the app with one of these lowercase values as `error` in the address. They aren't
HTTP errors. The app shows a message for them.

- `oauth_failed`: The provider reported a failure. **When:** you cancelled, or it sent back an error. **Do:** Try again.
- `bad_callback`: The provider's reply was incomplete. **When:** it's missing what Formerie needs. **Do:** Try again from the sign-in page.
- `invalid_state`: The sign-in attempt expired. **When:** it took too long, or finished in another browser. **Do:** Start again from the sign-in page.
- `provider_rejected`: The provider refused the exchange. **When:** after you approved it. **Do:** Try again, or use another method.
- `provider_not_configured`: This provider isn't available. **When:** it's not set up. **Do:** Use another method.
- `account_disabled`: This account is disabled. **When:** at sign-in. **Do:** Write to us.
- `user_not_found`: The account wasn't found. **When:** while connecting a provider to it. **Do:** Sign in again.
- `provider_email_required`: The provider gave no verified email. **When:** the account there has none. **Do:** Verify the email with the provider, or use another method.
- `provider_email_in_use`: Another account uses that provider's email. **When:** you connect a provider. **Do:** Use another provider account, or sign in to that account.
- `provider_in_use`: That provider account is connected to another account. **When:** you connect it. **Do:** Disconnect it there first.
- `provider_slot_in_use`: You already have an account from this provider connected. **When:** you connect a different one. **Do:** Disconnect the existing one first.

## Managing your workspace

Workspaces, people, domains, recipients, senders, providers, and templates in the app.

### Workspaces, forms, and responses

- `WORKSPACE_NOT_FOUND` (HTTP 404): The workspace doesn't exist, or you can't see it. **When:** a wrong ID, or lost access. **Do:** Check the address, or ask an owner.
- `WORKSPACE_HANDLE_CONFLICT` (HTTP 409): That public handle is taken. **When:** you create or rename a workspace. **Do:** Choose another.
- `WORKSPACE_ID_CONFLICT` (HTTP 409): A workspace with this ID already exists. **When:** you create one with an ID already in use. **Do:** Try again with another handle.
- `WORKSPACE_HAS_FORMS`, `WORKSPACE_HAS_MEMBERS` (HTTP 409): The workspace can't be permanently deleted yet. **When:** it still has forms, or other members. **Do:** Remove them first.
- `WORKSPACE_NOT_DELETED` (HTTP 409): It isn't in the trash. **When:** you permanently delete it directly. **Do:** Move it to the trash first.
- `FORM_HANDLE_CONFLICT` (HTTP 409): That handle is taken in this workspace. **When:** you create or rename a form. **Do:** Choose another.
- `FORM_HAS_SUBMISSIONS` (HTTP 409): The form can't be permanently deleted yet. **When:** it still has submissions. **Do:** Delete them first. See [Delete your data](/guides/delete-your-data/).
- `FORM_NOT_DELETED` (HTTP 409): It isn't in the trash. **When:** you permanently delete it directly. **Do:** Move it to the trash first.
- `SUBMISSION_NOT_FOUND` (HTTP 404): The response doesn't exist, or you can't see it. **When:** it was deleted, or the ID is wrong. **Do:** Open it from **Submissions**.

### Members and invitations

- `MEMBERSHIP_NOT_FOUND` (HTTP 404): That member wasn't found. **When:** they were removed. **Do:** Reload the list.
- `WORKSPACE_MEMBER_CONFLICT`, `FORM_MEMBER_CONFLICT` (HTTP 409): This email already has access. **When:** you add or invite them. **Do:** Change their existing access instead.
- `FORM_MEMBER_NOT_FOUND` (HTTP 404): That form member wasn't found. **When:** they were removed. **Do:** Reload the list.
- `WORKSPACE_LAST_OWNER` (HTTP 409): A workspace must keep an active owner. **When:** you remove or demote the last one. **Do:** Make someone else owner first.
- `WORKSPACE_SELF_OWNER` (HTTP 409): You can't change your own owner access. **When:** you try it on yourself. **Do:** Ask another active owner.
- `WORKSPACE_INVITATION_CONFLICT`, `FORM_INVITATION_CONFLICT` (HTTP 409): This email already has a pending invitation. **When:** you invite them again. **Do:** Resend the existing one.
- `WORKSPACE_INVITATION_NOT_FOUND`, `FORM_INVITATION_NOT_FOUND` (HTTP 404): That invitation wasn't found. **When:** it was removed or already used. **Do:** Reload, or send a new one.
- `WORKSPACE_INVITATION_INVALID` (HTTP 400): The invitation link is invalid or expired. **When:** you open an old link. **Do:** Ask for a new invitation.
- `WORKSPACE_INVITATION_MEMBERSHIP_DISABLED`, `FORM_INVITATION_MEMBERSHIP_DISABLED` (HTTP 403): Your access to this workspace was disabled. **When:** you accept an invitation. **Do:** Ask a workspace admin to restore it.
- `INVITATION_EMAIL_MISMATCH` (HTTP 403): The invitation was sent to another address. **When:** you're signed in with a different email. **Do:** Sign in with that address.

### Domains

- `DOMAIN_NOT_FOUND`, `DOMAIN_OWNERSHIP_NOT_FOUND` (HTTP 404): The domain wasn't found. **When:** it was removed, or isn't in this workspace. **Do:** Reload **Domains**.
- `DOMAIN_NOT_VERIFIED` (HTTP 409): The domain isn't verified yet. **When:** you enable it first. **Do:** Finish the DNS steps, and choose **Verify DNS**.
- `DOMAIN_HOSTNAME_RESERVED` (HTTP 400): Formerie reserves this hostname. **When:** you add it. **Do:** Use another.
- `DOMAIN_HOSTNAME_CONFLICT` (HTTP 409): The hostname is already connected to a workspace. **When:** you add it again. **Do:** Remove it there first.
- `DOMAIN_OWNED_BY_OTHER_WORKSPACE` (HTTP 409): Another workspace verified the domain above this hostname. **When:** you add it. **Do:** Add it from that workspace.
- `DOMAIN_OWNERSHIP_CONFLICT` (HTTP 409): This domain is already verified in the workspace. **When:** you add it again. **Do:** Use the existing one.
- `DOMAIN_OWNERSHIP_SCOPE_MISMATCH` (HTTP 409): The hostname isn't under the chosen domain. **When:** they don't match. **Do:** Choose the matching verified domain.
- `DOMAIN_ROUTE_CONFLICT` (HTTP 409): Another form uses this hostname and path. **When:** you connect a form. **Do:** Choose another path.
- `DOMAIN_HAS_ROUTES`, `DOMAIN_OWNERSHIP_HAS_ROUTES` (HTTP 409): The domain still has form routes. **When:** you permanently delete it. **Do:** Remove the routes first.
- `DOMAIN_NOT_DELETED`, `DOMAIN_OWNERSHIP_NOT_DELETED` (HTTP 409): It isn't in the trash. **When:** you permanently delete it directly. **Do:** Move it to the trash first.
- `HOSTNAME_BINDING_CONFLICT` (HTTP 409): Another subdomain uses that connection. **When:** you connect a form or workspace. **Do:** Choose another.
- `HOSTNAME_BINDING_FORM_NOT_FOUND` (HTTP 404): That form isn't in this workspace. **When:** you connect a hostname to it. **Do:** Choose a form in this workspace.
- `CLOUDFLARE_CUSTOM_HOSTNAME_FAILED` (HTTP 502): The custom hostname couldn't be set up. **When:** our hosting provider refused or failed. **Do:** Try again, and write to us with the **Reference** if it repeats.

### Recipients

- `RECIPIENT_NOT_FOUND` (HTTP 404): The recipient wasn't found. **When:** it was removed. **Do:** Reload **Recipients**.
- `RECIPIENT_CONFLICT` (HTTP 409): This recipient already exists in the workspace. **When:** you add it again. **Do:** Use the existing one.
- `RECIPIENT_NOT_VERIFIED` (HTTP 409): Verify before activating. **When:** you activate one that hasn't confirmed. **Do:** Have them confirm by email.
- `RECIPIENT_NOT_VERIFIABLE` (HTTP 409): This recipient can't get a verification email. **When:** its status doesn't allow it. **Do:** Check its status under **Recipients**.
- `RECIPIENT_HAS_FORMS` (HTTP 409): Forms still use this recipient. **When:** you permanently delete it. **Do:** Remove it from those forms first.
- `RECIPIENT_NOT_DELETED` (HTTP 409): It isn't in the trash. **When:** you permanently delete it directly. **Do:** Move it to the trash first.

### Senders

- `SENDER_NOT_FOUND` (HTTP 404): The sender wasn't found. **When:** it was removed. **Do:** Reload **Senders**.
- `SENDER_CONFLICT` (HTTP 409): This sender already exists in the workspace. **When:** you add it again. **Do:** Use the existing one.
- `SENDER_NOT_VERIFIED` (HTTP 409): Verify before activating. **When:** you activate one that hasn't confirmed. **Do:** Confirm it by email.
- `SENDER_NOT_VERIFIABLE` (HTTP 409): This sender can't get a verification email. **When:** its status doesn't allow it. **Do:** Check its status under **Senders**.
- `SENDER_HAS_FORMS` (HTTP 409): Forms still use this sender. **When:** you permanently delete it. **Do:** Choose another sender on those forms first.
- `SENDER_NOT_DELETED` (HTTP 409): It isn't in the trash. **When:** you permanently delete it directly. **Do:** Move it to the trash first.

### Email providers

- `PROVIDER_CONNECTION_NOT_FOUND` (HTTP 404): That provider connection wasn't found. **When:** it was removed. **Do:** Reload **Destinations**.
- `PROVIDER_CONNECTION_REQUIRED` (HTTP 400): A sender needs a provider here. **When:** you save a sender without choosing one. **Do:** Choose an email provider.
- `PROVIDER_CONNECTION_CONFLICT` (HTTP 409): This provider connection already exists. **When:** you add it again. **Do:** Use the existing one.
- `PROVIDER_CONNECTION_NOT_DELETED` (HTTP 409): It isn't in the trash. **When:** you permanently delete it directly. **Do:** Move it to the trash first.
- `PROVIDER_CREDENTIAL_KEY_UNAVAILABLE` (HTTP 500): Credentials couldn't be encrypted. **When:** you save a provider or authenticator, and something is wrong on our side. **Do:** Try again later, and write to us with the **Reference**.

### Email templates

`TEMPLATE_INVALID` lists what's wrong in `error.issues`, each with one of the codes after it. See [Notification Templates](/guides/notification-templates/).

- `TEMPLATE_NOT_FOUND` (HTTP 404): The template wasn't found. **When:** it was removed. **Do:** Reload the list.
- `TEMPLATE_INVALID` (HTTP 422): The template can't be saved. **When:** it has syntax or HTML problems. **Do:** Read `error.issues`.
- `TEMPLATE_TAG_UNCLOSED`, `TEMPLATE_TAG_EMPTY`: A `{{ }}` tag is broken. **When:** it's never closed, or has nothing in it. **Do:** Close it, or fill it in.
- `TEMPLATE_EXPRESSION_INVALID`: A tag's expression can't be read. **When:** a path or its syntax is wrong. **Do:** Fix the tag.
- `TEMPLATE_FILTER_INVALID`: A tag uses a filter that doesn't exist. **When:** it's misspelled or unsupported. **Do:** Use a listed filter.
- `TEMPLATE_STRING_UNTERMINATED`: A quoted value in a tag never ends. **When:** a closing quote is missing. **Do:** Add it.
- `TEMPLATE_HTML_UNSAFE`: The HTML holds something that isn't safe to send. **When:** it has content the sanitizer refuses. **Do:** Remove what `message` names.
- `FORM_CONFIG_RECEIPT_PUBLIC_INPUT_VARIABLE`: A confirmation receipt can't repeat what was submitted. **When:** the template uses a submitted answer or a submission summary. **Do:** Remove that variable. See [Notification Templates](/guides/notification-templates/).

## Plans and limits

See [Plans and limits](/guides/plans-and-limits/) for what each plan includes, and what isn't enforced.

- `PLAN_LIMIT_ACTIVE_FORMS_REACHED`, `PLAN_LIMIT_RECIPIENTS_REACHED`, `PLAN_LIMIT_MEMBERS_REACHED`, `PLAN_LIMIT_PROVIDER_CONNECTIONS_REACHED`, `PLAN_LIMIT_RUNTIME_HOSTNAMES_REACHED` (HTTP 409): The workspace is at its plan's limit. **When:** you add or activate one more. `error.details` has the numbers, and nothing already saved changes. **Do:** Remove one you don't use, or move to a higher plan.
- `PLAN_SUBSCRIPTION_INACTIVE` (HTTP 409): The workspace's plan isn't active. **When:** it has ended or isn't running. **Do:** Check the plan under **Settings**, or write to us.
- `PLAN_ENTITLEMENT_UNAVAILABLE` (HTTP 503): The plan information couldn't be read. **When:** a temporary problem on our side. **Do:** Try again shortly.
- `ACCOUNT_STORAGE_HOLD` (HTTP 403): The account's forms paused new submissions. **When:** the account stores far more than normal use. Everything already received is safe. **Do:** [Write to us](https://formerie.com/contact/).
- `EMAIL_CEILING_REACHED`: The response is kept, and not emailed. **When:** the account reached its monthly ceiling for email sent through Formerie. It shows on the delivery attempt. **Do:** Retry from the 1st of next month, or write to us.

## AI and MCP (Coming soon)

The AI features built into Formerie and MCP access aren't available today. These codes are here so the list is complete, and they may change before release. Using your own coding agent is separate: see [Use your AI](/guides/quickstart-ai/).

### Using AI

- `AI_NOT_CONFIGURED` (HTTP 503): AI features aren't available right now. **When:** AI isn't set up for this request. **Do:** Keep working without it.
- `AI_PAUSED` (HTTP 503): AI is taking a short break. **When:** AI use is paused for now. Everything you built still works. **Do:** Try again later.
- `AI_LIMIT_REACHED` (HTTP 429): This month's AI has been used. **When:** the allowance runs out. **Do:** Wait for the 1st.
- `AI_PROVIDER_UNAVAILABLE` (HTTP 503): The AI service isn't available. **When:** it can't be reached. **Do:** Try again in a moment.
- `AI_TIMEOUT` (HTTP 504): The AI service took too long. **When:** it didn't answer in time. **Do:** Try again.
- `AI_OUTPUT_INVALID` (HTTP 422): The AI result couldn't be used. **When:** it wasn't a valid answer. **Do:** Reword your request.
- `AI_REQUEST_REFUSED` (HTTP 422): The AI service declined. **When:** it refused this request. **Do:** Reword your request.
- `AI_GENERATION_NOT_FOUND` (HTTP 404): That AI result wasn't found. **When:** it expired or was already used. **Do:** Generate it again.

### AI suggestions

These are warnings on a draft or a rule, for you to review. They don't stop anything.

- `AI_RECIPIENTS_NOT_SET`: The draft has no recipients. **When:** the form was drafted without any. **Do:** Add one under **Delivery**.
- `AI_SENSITIVE_FIELD_REMOVED`: A sensitive field was left out. **When:** the AI proposed one, and Formerie didn't add it. **Do:** Check the form's fields.
- `AI_RULE_REMOVED`: A proposed rule was left out. **When:** it depended on a field that was left out. **Do:** Add it yourself if you need it.
- `AI_RULE_REPLACES_EXISTING`: This rule would replace one. **When:** the field already has a visibility rule. **Do:** Review before applying.
- `AI_NO_SAMPLES`, `AI_SAMPLE_MISMATCH`: The rule's examples don't confirm it. **When:** there are none, or one gives a different result than expected. **Do:** Test the rule before applying it.

### Smart routing

- `AI_ROUTING_INVALID` (HTTP 400): The routing settings aren't valid. **When:** you save them. **Do:** Check the routes.
- `AI_ROUTING_NOT_CONFIGURED` (HTTP 409): This form has no routing. **When:** you act on a response. **Do:** Set it up first.
- `AI_ROUTING_CONFLICT` (HTTP 409): The routing changed since you loaded it. **When:** someone saved first. **Do:** Reload and try again.
- `AI_ROUTING_DELIVERY_NOT_CONFIGURED` (HTTP 409): Routing needs a recipient. **When:** you turn it on with none. **Do:** Add a form recipient.
- `AI_ROUTING_NOT_ACTIONABLE` (HTTP 409): This response can't be changed now. **When:** it's no longer waiting for a decision. **Do:** Reload it.
- `AI_ROUTING_RECIPIENT_UNAVAILABLE` (HTTP 422): A route uses an unverified recipient. **When:** you save it. **Do:** Verify the recipient, or choose another.
- `AI_ROUTE_NOT_FOUND` (HTTP 422): That route isn't in this form's routing. **When:** you choose one that was removed. **Do:** Reload the routes.
- `NO_TEXT`, `ROUTE_NO_MATCH`, `ROUTE_NOT_LISTED`, `ROUTE_LOW_CONFIDENCE`, `ROUTE_UNAVAILABLE`, `SPAM_LOW_CONFIDENCE`, `AI_INTERRUPTED`: Why a response went to the fallback route, as its `reasonCode`. **When:** there was nothing to read, no clear match, the route wasn't usable, or the check was cut short. **Do:** Review the response, and adjust the routes if it repeats.

### MCP and API keys

- `AI_CREDENTIAL_INVALID` (HTTP 401): The connection is no longer valid. **When:** it was revoked or expired. **Do:** Connect again.
- `AI_SCOPE_DENIED` (HTTP 403): The connection lacks a permission. **When:** a tool needs what `requiredScope` names. **Do:** Grant it, then connect again.
- `AI_ROUTE_NOT_ALLOWED` (HTTP 403): AI connections can't do this. **When:** an operation is kept for the app. **Do:** Do it in the app.
- `AI_CREDENTIAL_APP_ONLY` (HTTP 400): Credentials can't be set through an AI tool. **When:** a tool call holds a secret. **Do:** Enter it in the app.
- `AI_WORKSPACE_REQUIRED` (HTTP 400): The connection covers several workspaces. **When:** a call doesn't name one. **Do:** Pass `workspaceUid`.
- `AI_RATE_LIMITED` (HTTP 429): Too many requests from this connection. **When:** in a short time. **Do:** Wait, then try again.
- `AI_CONFIRMATION_INVALID` (HTTP 409): The confirmation can't be used. **When:** it expired, was already used, or was for other arguments. **Do:** Start again, and ask the person.
- `AI_CONFIRMATION_UNAVAILABLE` (HTTP 403): This action needs a person's approval, and this client can't ask. **When:** a high-impact tool runs in that client. **Do:** Do it in the app, or use a client that can ask.
- `AUDIT_UNAVAILABLE` (HTTP 503): The action didn't run because it couldn't be recorded. **When:** a temporary problem on our side. **Do:** Try again shortly.
- `AI_CONSENT_NOT_FOUND` (HTTP 404): The authorization request wasn't found. **When:** it expired or was already used. **Do:** Start again from the app.
- `AI_GRANT_NOT_FOUND` (HTTP 404): That AI connection wasn't found. **When:** it was removed. **Do:** Reload the list.
- `AI_API_KEY_NOT_FOUND` (HTTP 404): That API key wasn't found. **When:** it was removed. **Do:** Reload the list.
- `AI_API_KEY_LIMIT_REACHED` (HTTP 409): You have too many API keys. **When:** you create one more. **Do:** Revoke one first.

## SDK

`@formerie/client` adds its own codes for what never reached Formerie. It can also return some server codes without a request: a
failed verification step gives `TURNSTILE_FAILED`, a non-JSON 429 gives `RATE_LIMITED`, and a form bound without a target, or submitted
twice at once, gives `BAD_REQUEST`.

- `NETWORK_ERROR`: The request never completed. **When:** the network failed, or the browser blocked it, often over CORS. **Do:** See [A CORS or Origin error](/guides/troubleshooting/#a-cors-or-origin-error), and let the visitor retry.
- `INVALID_RESPONSE`: The reply wasn't a Formerie response. **When:** something between you and Formerie answered instead, or the address is wrong. **Do:** Check the endpoint, then look at the response in the network panel.

### Loading the script

From `cdn.formerie.com`.

- `ASSET_NOT_FOUND` (HTTP 404): That file doesn't exist. **When:** the path or version is wrong. **Do:** Copy the address from your **Embed code**, or the [SDK guide](/guides/javascript-sdk/).
- `METHOD_NOT_ALLOWED` (HTTP 405): The CDN only reads. **When:** a request isn't `GET`, `HEAD`, or `OPTIONS`. **Do:** Use `GET`.

## Any request

These can come from any route.

- `BAD_REQUEST` (HTTP 400, 404, 409, 413): The request couldn't be processed. **When:** a value is invalid (400), the route doesn't exist (404), a passkey is already connected (409), or a body is too large (413). `message` says which. **Do:** Fix the request. A submission must send `{ "fields": { ... } }` under 100,000 bytes.
- `INVALID_JSON` (HTTP 400): The body isn't valid JSON. **When:** it can't be parsed. **Do:** Fix what your code sends.
- `FORBIDDEN` (HTTP 403): You don't have access. **When:** your role doesn't allow this. **Do:** Ask a workspace owner or admin. See [Team and access](/guides/team-and-access/).
- `INTERNAL_ERROR` (HTTP 500): Something went wrong on our side. **When:** an unexpected failure. **Do:** Try again shortly, and write to us with the **Reference** if it repeats.
