Skip to content
Working With Vue

Handling errors in Vue

Handle Qubeforms API errors in Vue forms while preserving visitor input. Manage validation feedback, rate limits, network loss, navigation, and duplicate submissions.

1. Keep form and request state separate

Use ref for pending and feedback state and reactive or individual refs for entered values. The basic Vue component blocks concurrent submits and snapshots FormData before disabling fields. Browser validation handles common missing or malformed inputs, while server errors still need their own visible message.

2. Parse responses defensively

Keep existing field values after an error and clear them only after response.ok and result.ok === true. Use error.message for server feedback and render it as text, not HTML. The API does not promise a per-field error map, so do not assume error.details always contains field names. A proxy may return HTML or an empty body; guard JSON parsing and retain a fallback message. A network exception does not prove that the submission failed to arrive.

const result = await response.json().catch(() => null);
if (!response.ok || result?.ok !== true) {
  feedback.value = result?.error?.message || `Could not confirm receipt (HTTP ${response.status}).`;
  return;
}
// Reset reactive values only after confirmed success.

3. Use status-specific guidance

Read both HTTP status and error.message. For XHR use xhr.status and guarded parsing of xhr.responseText. These are API errors rather than Vue template errors. A 422 redirect error can occur after storage; check the inbox before repeating it.

402  The plan does not allow this feature, such as file uploads.
403  Origin or access restriction.
404  Form or requested resource unavailable.
413  Request or payload too large.
422  Validation, CAPTCHA, attachment, or redirect error; inspect error.message.
429  Rate, storage, or usage limit; follow Retry-After when present.
500  Server error; receipt may be uncertain.
503  Service or storage unavailable.

4. Respect rate limits and duplicate protection

Read the Retry-After delay in seconds on 429 and show it to the visitor. The basic Vue examples display the delay but do not enforce a countdown. Do not automatically resend from a watcher, on remount, or in a tight loop. If you implement retries with Idempotency-Key, retain one key for the unchanged logical submission; changing values requires a new key. Reusing a key returns the existing record without comparing a new payload, and each HTTP attempt still consumes rate-limit capacity.

5. Handle network loss and navigation

Keep entered values after failure and reset them only on confirmed success. If a request is aborted or times out, do not assume the server discarded it. A route change can unmount the component; the upload-progress example aborts its request locally but cannot undo server-side work. Avoid rendering messages with v-html; {{ feedback }} displays untrusted error text without treating it as markup.

6. Test before deploying

Test malformed input, invalid origin, expired CAPTCHA, large attachments, non-JSON errors, and offline mode. Verify that the loading state always ends and that fields remain available. A successful response may describe a Spam record and does not promise email delivery; inspect the returned status and delivery records when troubleshooting.

Keep private credentials private

Public form keys can appear in browser code. Read keys, management credentials, and webhook signing secrets must stay on the server.