Draft saving and duplicate submissions
Fix Qubeforms draft save failures and duplicate submissions. Check draft tokens, expiration, and field state, prevent stale updates, and recover from uncertain responses.
1. Separate draft saves from final submission
A draft-create response contains draft_id, draft_token, and expires_in; an update contains saved: true. Neither is a final submission or a notification trigger. Finish by posting to /submissions with the draft ID and token in the body. See Create and update drafts for the endpoint reference.
2. Resolve token and expiration errors
On update, send the original token in X-Qubeforms-Draft-Token and use the same form’s public key. 404 can mean the token is wrong, the draft belongs elsewhere, or it was already completed or purged. 410 means it expired but remains stored. Default lifetime is 72 hours from creation; saving again does not renew it. Preserve local fields and explicitly start a fresh draft if the old one is unavailable.
3. Prevent stale or lost fields
Wait for a save to complete before another update or final POST. Updates recursively merge with saved values, so omitting a field does not remove it. Keep fields for earlier steps in parent state and send explicit intended values. Qubeforms does not provide a customer GET endpoint to reconstruct the UI. An in-memory token and state disappear on reload, and file inputs may need reselection. Do not promise resumability unless your application securely implements it.
4. Investigate duplicate final submissions
Check for repeated click handlers, both native and JavaScript submission, automatic retries after timeouts, or multiple requests in the Network panel. Disable submit during a request. Give each intentional final submission one random Idempotency-Key and reuse it only for retries of that same request. Generating a fresh key on every retry defeats deduplication. Draft IDs alone are not a replacement for final-request idempotency.
5. Recover from an uncertain result
A timeout does not prove the save or submission failed. For a final POST, inspect the inbox or retry with the original idempotency key and payload. A successful final POST consumes the draft, so a later missing-draft error can follow an already accepted request. Draft creation has no idempotency support and retrying it can create another draft. Keep the visitor informed and avoid claiming receipt until you can confirm it.
Public form keys can appear in browser code. Read keys, management credentials, and webhook signing secrets must stay on the server.