FAQ & Troubleshooting
The embed
Section titled “The embed”The embed shows “This questionnaire is not available.”
Section titled “The embed shows “This questionnaire is not available.””The public id resolves to nothing live. In order of likelihood:
- The questionnaire was never published. A draft isn’t visible to embeds — click Publish changes in the editor. (The live endpoint 404s until version 1 exists.)
- The
public-idhas a typo — copy it from the editor’s Embed panel. - The
api-basepoints at the wrong backend.
The embed shows “The questionnaire could not be loaded.”
Section titled “The embed shows “The questionnaire could not be loaded.””The request itself failed. Check, in order:
- Is the backend reachable from the browser? Open
{api-base}/public/v1/questionnaires/{publicId}/livein a tab. - Mixed content: an
https://page cannot call anhttp://api-base — browsers block it. Serve the backend over HTTPS. - Allowed origins: if the questionnaire has an origin list and your page’s origin isn’t on it, the browser blocks the read (the devtools console shows a CORS error). Add your origin in the Embed panel — exact match, scheme and port included.
The form renders, but a red “answers aren’t saving” banner appears
Section titled “The form renders, but a red “answers aren’t saving” banner appears”Saves are failing after retries. The usual causes: the origin isn’t allowed (mutating calls return 403 — check the network tab), the backend went down mid-session, or a proxy strips the request. The form keeps the respondent’s answers in memory and keeps retrying on each screen change.
“This form is misconfigured: an external reference is required.”
Section titled ““This form is misconfigured: an external reference is required.””The questionnaire’s submission policy is one-per-reference and the embed
has no external-ref attribute. That’s a deliberate loud failure — add
the reference. See
External references.
A refreshed page doesn’t resume the session in a new tab / after a browser restart
Section titled “A refreshed page doesn’t resume the session in a new tab / after a browser restart”By design. Resume uses sessionStorage, which is per-tab and doesn’t survive browser restarts — because with spoofable references, anything longer-lived would let a guessed reference unlock someone else’s session. Cross-device resume arrives with signed references (roadmap).
The React/Angular wrapper doesn’t accept labels / completion-redirect / persist-session
Section titled “The React/Angular wrapper doesn’t accept labels / completion-redirect / persist-session”Correct — the current wrappers expose publicId, apiBase, and
externalRef only. Use the web component directly for the rest; it’s the
same renderer. See the note in React /
Angular.
My “not equals” rule doesn’t fire for people who haven’t answered yet
Section titled “My “not equals” rule doesn’t fire for people who haven’t answered yet”By design: no condition is ever true against an unanswered question,
including not equals. “Show unless they picked X” therefore means
“show once they picked something other than X”. The same applies to
does not contain and to equals false on an untouched toggle. Full
semantics: Rules.
An answer disappeared when I changed an earlier answer
Section titled “An answer disappeared when I changed an earlier answer”That’s answer clearing: hiding a question deletes its answer, and the clearing cascades through dependent rules. It’s what keeps hidden answers from secretly driving logic. Details.
Why can’t a rule reference my file-upload question?
Section titled “Why can’t a rule reference my file-upload question?”There’s nothing meaningful to compare — rules would end up matching on file names. File questions can have rules; they can’t be referenced by them. Why.
Uploads & storage
Section titled “Uploads & storage”Uploads fail with cryptic DNS or 403 errors
Section titled “Uploads fail with cryptic DNS or 403 errors”Check S3_PATH_STYLE first. MinIO, R2, B2, and most S3-compatibles need
true (path-style); real AWS needs false. This is the single most
common storage misconfiguration.
Storage.
The backend won’t start and mentions a “canary”
Section titled “The backend won’t start and mentions a “canary””Working as intended: the startup canary write/read/delete failed, so the backend refused to start rather than accept uploads it would lose. The error message names the settings to check (bucket exists? credentials? path writable?).
A legitimate-looking file is rejected
Section titled “A legitimate-looking file is rejected”The server verifies file content, not names. A .pdf that is really
a zip, a .csv that contains binary, or anything that sniffs as
HTML/script is rejected with a specific message. If the file is genuinely
what its extension claims and still bounces, that’s a bug worth
reporting.
Address autocomplete
Section titled “Address autocomplete”Suggestions never appear
Section titled “Suggestions never appear”Autocomplete degrades silently when the geocoder is unreachable — manual
entry keeps working, so nothing looks “broken”. Check that
PHOTON_BASE_URL is reachable from the backend, remember suggestions
start at the third typed character, and note the public Photon
instance is fair-use (it may throttle you —
self-host for production).
Operations
Section titled “Operations”I’m getting 429s while testing
Section titled “I’m getting 429s while testing”All your test traffic comes from one IP, and the public API rate-limits
per IP. Set FORMS_RATE_LIMIT_ENABLED=false in development. If this
happens in production behind a reverse proxy, you’ve likely hit the
proxy-IP problem — every visitor is sharing one bucket. Fix:
rate limiting behind a proxy.
The editor’s questionnaire list stops at 100
Section titled “The editor’s questionnaire list stops at 100”Known limitation: the list shows the 100 most recently updated
questionnaires and has no pager yet. The management API paginates
(GET /api/v1/questionnaires?page=&size=) if you need the rest.
CSV values show a leading apostrophe in Excel
Section titled “CSV values show a leading apostrophe in Excel”That’s the formula-injection guard: text answers starting with =, +,
-, or @ are quote-prefixed so respondent input can’t execute as a
formula. The apostrophe is Excel’s “treat as text” marker and doesn’t
appear in the stored data.
Where is my data, exactly?
Section titled “Where is my data, exactly?”Responses: the responses collection in MongoDB
(docker compose exec mongo mongosh forms_engine --eval 'db.responses.find().pretty()'). Definitions and versions:
questionnaires and questionnaire_versions. Uploaded file index:
uploaded_files; the bytes are in your storage backend under
server-generated keys.
Why doesn’t a response appear the moment someone opens the form?
Section titled “Why doesn’t a response appear the moment someone opens the form?”Response creation is lazy — it happens on the first forward navigation or first upload, so page views don’t create empty rows. Lifecycle.