Skip to content

Troubleshooting

Find what’s wrong and get your form working again. Each section starts from what you see, shows how to check it, and gives the fix. Formerie returns stable codes, and this page uses their exact names.

The sections:

My Email Didn’t Arrive

Symptom: someone filled in the form, and the email never showed up.

How to check: open Deliveries in the app and find the response by form and date. Each row has a status, and a diagnostic with a code, a summary, and a next step. The same details are on the response itself under Submissions. Then find what you see in this table.

What you seeWhat it meansWhat to do
No response in SubmissionsIt was refused before it was storedSee A Submission Was Rejected
A response with no deliveryThe form had no recipients, so it was only storedAdd a recipient under Delivery. New responses get email from then on. Earlier ones were never sent, and a retry doesn’t send them
QueuedWaiting for its attemptWait a moment
RetryingA temporary problem with the provider. Formerie tries up to 5 times, 60 seconds apartWait, unless the diagnostic is DELIVERY_STALLED
FailedThe email couldn’t be sentFind the code in the next table, fix it, then choose Retry delivery
DeliveredThe provider accepted the emailSee Delivered, But Not In The Inbox

Delivery Diagnostic Codes

CodeWhat the app saysFix
DELIVERY_RECIPIENTS_UNAVAILABLENo active verified recipients are configured for this formHave the recipient confirm by email, or add another one, under Delivery
DELIVERY_SENDER_UNAVAILABLEThe selected sender identity is not active or verifiedConfirm the sender under Senders, or set Send from back to the Formerie default
DELIVERY_CREDENTIALS_MISSINGThe delivery provider is missing required credentialsReconnect the provider under Destinations
DELIVERY_PROVIDER_NOT_FOUNDThe configured email provider could not be usedReview the provider under Destinations and on the Delivery tab
DELIVERY_PROVIDER_UNREACHABLEThe delivery provider could not be reachedCheck the provider’s status, then retry
DELIVERY_PROVIDER_ERRORThe provider did not accept the deliveryCheck the provider’s status and your settings with them, then retry
DELIVERY_FAILEDDelivery failed before the provider accepted the messageReview the sender, recipients, and provider, then retry
DELIVERY_STALLEDDelivery stopped retrying after a temporary errorOpen the response and retry
DELIVERY_PROVIDER_UNREACHABLE_RETRYINGThe delivery provider could not be reachedNothing yet. Formerie will try again
DELIVERY_PROVIDER_TEMPORARY_ERRORThe provider returned a temporary delivery errorNothing yet. Formerie will try again
DELIVERY_QUEUED, DELIVERY_WAITING_FOR_ATTEMPTDelivery is waiting for an attemptNothing yet
DELIVERY_ACCEPTED, DELIVERY_COMPLETEDThe provider accepted the emailSee the next section if it still hasn’t arrived

Delivered, But Not In The Inbox

Delivered means the provider took the email. It doesn’t prove it reached the inbox.

  1. Ask the recipient to check their spam folder.
  2. If you use your own email provider, search its logs for the message.
  3. Open the form’s Delivery tab, and make sure that address is on the form.
  4. Open Recipients, and look at that address. A Pending, Disabled, or Suppressed recipient gets nothing. A suppressed address usually bounced or marked a message as spam.

Only Some People Got It

A recipient with a condition only gets the responses that match it. Compare the condition on the Delivery tab with the answers in the response. If a condition leaves nobody to send to, the response is kept and no email goes out, and that isn’t counted as a failure.

Retry A Delivery

Fix the cause first, because most failures repeat otherwise. Then open the response under Submissions and choose Retry delivery. It sends real email with the form’s current delivery settings, and doesn’t change the response.

CodeMeaning
DELIVERY_NOT_RETRYABLEThis delivery can’t be retried right now, for example because it was already delivered
DELIVERY_ATTEMPT_IN_PROGRESSAn attempt is running. Wait for its result
QUEUE_FAILEDThe retry couldn’t be queued. Try again shortly

A Test Email Won’t Send

CodeCauseFix
FORM_DELIVERY_TEST_NOT_READYA sender or recipient isn’t ready, or the form has no recipientsFollow the items under Delivery readiness
FORM_DELIVERY_TEST_NO_RECIPIENTSThe sample answers match no recipientChange the sample answers under Preview, or review recipient conditions
FORM_DELIVERY_TEST_RATE_LIMITEDYou can send one test per minuteWait a minute
FORM_DELIVERY_TEST_SEND_FAILEDThe provider refused itCheck the sender and provider, then try again

A Submission Was Rejected

Symptom: the visitor sees an error, or your code gets ok: false.

How to check: a refused submission isn’t stored, so it never appears under Submissions. Read the code in the response instead, in your browser’s network panel or from result.error.code in the SDK. It looks like this:

JSON
{
  "ok": false,
  "error": {
    "code": "SPAM_REJECTED",
    "message": "The submission was rejected."
  }
}

The server runs its checks in order and stops at the first one that fails: origin, availability, rate limit on public routes, response window, size, format, repeat send, submission limits, spam checks, human verification, answers, and quota.

CodeHTTP statusCauseFix
VALIDATION_FAILED422An answer failed a checkSee Failed Answers
SPAM_REJECTED403A spam check caught itSee Rejected As Spam
TURNSTILE_FAILED403Human verification failed, with any providerSee Verification Failed
RATE_LIMITED429Too many submissions in a short timeSee Too Many Submissions
FORM_QUOTA_REACHED409The form hit its Maximum accepted submissionsRaise or clear it under Submission limits, in Settings
DUPLICATE_SUBMISSION409This metadata.idempotencyKey was already acceptedTreat it as a success. See Repeat Sends
FORM_NOT_OPEN403Before the Response window opensChange the window on the Publish tab
FORM_CLOSED403The form is closed, or its window has endedChange Public access or the window on the Publish tab
FORM_MAINTENANCE503Public access is on MaintenanceSet it back to Public
FORM_NOT_FOUND404Wrong address, or the form isn’t publishedSee The Form Isn’t Showing
FORBIDDEN_ORIGIN403The browser’s site isn’t an allowed originSee A CORS Or Origin Error
BAD_REQUEST400 or 413The body has no fields object, or is over 100,000 bytesSend { "fields": { ... } }, and shorten large answers
INVALID_JSON400The body isn’t valid JSONFix what your code sends
QUEUE_FAILED503The email couldn’t be queuedAsk the visitor to try again shortly
INTERNAL_ERROR500Something went wrong on our sideTry again shortly

Failed Answers

VALIDATION_FAILED lists each problem in error.fields and error.issues, with a path, a code, and a message:

JSON
{
  "ok": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "The submitted form contains invalid fields.",
    "fields": {
      "contact.email": [
        {
          "path": "contact.email",
          "code": "FIELD_EMAIL_INVALID",
          "message": "Invalid email address.",
          "rule": "email",
          "params": {}
        }
      ]
    },
    "issues": [
      {
        "path": "contact.email",
        "code": "FIELD_EMAIL_INVALID",
        "message": "Invalid email address.",
        "rule": "email",
        "params": {}
      }
    ]
  }
}

Show each message next to its field. Hosted pages and embeds do this for you. The codes are listed by field type in the Form Definition Reference, and your own validators return the code you gave them.

A field that’s required but hidden can’t fail, because the server skips hidden fields. If a required field keeps failing, check that your own UI sends it under the exact name, with groups as nested objects.

Rejected As Spam

The response doesn’t say which check caught it, so go through all three under Settings, in Anti-spam:

CheckWhat trips itFix
Hidden fieldThe hidden field has a value. New forms use _formerie_hpIn your own UI, leave that field out or empty
Minimum submit timemetadata.startedAt is more recent than the limit, 1 second on new formsSet startedAt when the form first appears, not on submit, or lower the limit
Maximum linksMore links than the limit across all answers, 3 on new forms. Web addresses in url fields count tooRaise the limit. 0 rejects any link, and an empty setting turns the check off

Too Many Submissions

RATE_LIMITED comes from one of two places:

  • Submission limits, under Settings. New forms allow 10 submissions per visitor every 10 minutes, and 300 for the whole form every hour. Raise them if your form gets real bursts. People on the same network, such as an office, share the per-visitor limit.
  • A short-term limit on public routes, which you can’t change. It sends Retry-After, in seconds.

Tell the visitor to wait, and keep their answers on screen.

Repeat Sends

DUPLICATE_SUBMISSION means the first send already worked, and that’s good news. Show your success message. Send a new metadata.idempotencyKey for each new submission, and reuse a key only to retry the same one.

The Form Isn’t Showing

Symptom: the link shows an error, or the page where you embedded the form is blank.

How to check: open the form’s Hosted URL in a private window. If it works there, the form is fine and the problem is in the page around it. If you see a line of JSON, read its code.

What you seeCauseFix
FORM_NOT_FOUNDThe form was never published, Public access is on Unpublished, or the address is wrongPublish on the Publish tab, and copy the address from there
FORM_CLOSED, FORM_NOT_OPENThe form is closed, or outside its Response windowChange them on the Publish tab
FORM_MAINTENANCEPublic access is on MaintenanceSet it back to Public
FORM_NOT_FOUND on your own hostnameThe hostname isn’t active or isn’t connected to this formFinish the DNS steps under Domains, and check its connection
“The form could not be loaded.” or “Loading form…”The browser couldn’t load the form’s scriptCheck for a blocked request to cdn.formerie.com in the browser’s network panel
An old version of the formYour changes are still a draftChoose Publish changes
A question is missingA condition is hiding it, or it’s on a later stepReview Conditions and Flow

An Embed Shows Nothing

  • The script adds its iframe right where the tag sits. With data-formerie-target, the selector has to match something on the page when the script runs.
  • data-formerie-form must be workspace-handle/form-handle, as in the Embed code. A wrong value shows FORM_NOT_FOUND inside the iframe.
  • If your site sets a Content Security Policy, allow https://forms.formerie.com as a frame and script source, and https://cdn.formerie.com as a script source.

A Browser Mount Shows Nothing

The browser mount loads the form with a call from your page. Without your site’s address in the allowed origins, that call fails. See the next section.

A CORS Or Origin Error

Symptom: your browser’s console shows blocked by CORS policy, your code gets a network error such as Failed to fetch or the SDK’s NETWORK_ERROR, and the request shows as 403 or 404 in the network panel. Your code doesn’t get to read a Formerie code, because a refused browser request comes back without the headers that would let it.

How to check: this only happens when browser code on your own site calls Formerie, which means the browser mount, a framework package used in the browser, or your own fetch. A hosted link and a script embed don’t call from your site, so they can’t cause it.

Open the failed request in the network panel. It’s often the OPTIONS one, and its response says FORBIDDEN_ORIGIN or FORM_NOT_FOUND. Compare the request’s Origin header with your list.

CauseFix
Your site isn’t listedAdd it under Your website addresses on the Publish tab, or Allowed origins in Settings, then publish
You added it but didn’t publishOrigins take effect when you publish. Publish saves them for you
The address differs slightlyMatches are exact. https://example.com, https://www.example.com, and http://example.com are three entries, so add each one your site answers on
You’re testing locallyAdd your dev address with its port, such as http://localhost:5173
You used a path or a wildcardUse the address only. Paths fail with FORM_CONFIG_ORIGIN_INVALID, and * with FORM_CONFIG_ORIGIN_WILDCARD
The response says FORM_NOT_FOUNDThe workspace or form handle is wrong, or the form isn’t published. It looks like a CORS error because no form means no list of origins to allow
You added your own request headerBrowsers may only send Content-Type here. Remove the custom header, or send it from your server

Code on your own server doesn’t need any of this, unless it forwards an Origin header. Without one, the check doesn’t apply. See Allowed Origins.

Verification Failed

Symptom: a submission returns TURNSTILE_FAILED. It’s the same code for Cloudflare Turnstile and for reCAPTCHA, and the response doesn’t give a reason.

How to check: look at the form’s Human verification settings under Settings, then go through these causes.

CauseFix
No token was sentYour own UI needs to pass the provider’s token as verificationToken. Hosted pages, embeds, and the browser mount handle this for you
The token was already used, or expiredTokens work once. Get a new one for each attempt, including after a failed submit
The widget’s domain doesn’t matchFormerie checks that the token came from the site making the request. See the next section
Formerie managed on your own siteManaged keys work on supported Formerie-hosted domains. Use your own keys for your own domain
Wrong keysThe site key and secret key must come from the same widget. Save them again under Human verification
Expected action doesn’t matchIt must match the action your widget sends
reCAPTCHA v3 score too lowLower Minimum score, from 0 to 1

Which Domain To Add To Your Widget

With your own keys, the provider’s console lists the domains your widget works on. Add the domain the widget loads on:

How you publishDomain to add
Hosted linkforms.formerie.com, or your own connected hostname
Script embedforms.formerie.com, or your own connected hostname, because the widget runs inside the iframe
Browser mount or your own UIYour own site

Verification Through Your Own Server

A token from your page, sent on through your own server, can fail on the domain check. Without an Origin header, Formerie compares the token’s domain with its own. To pass, forward the visitor’s Origin header with the request, and list that site under allowed origins too.