Troubleshooting

Debug common adoption problems by symptom. Each item maps directly to a root cause and a minimal correction.

I click submit and nothing happens.

Likely cause: handleSubmit is not wired correctly, submit button type is wrong, or client validation blocked execution.

Quick fix: Use onSubmit={handleSubmit()} and inspect formState.errors after click.

Action is not called even with valid-looking fields.

Likely cause: Client-side schema validation failed before the network request.

Quick fix: Check validationMode and verify each field against the schema.

Server errors are not shown on inputs.

Likely cause: Returned error shape does not match default mapper expectations.

Quick fix: Return { errors: Record<string, string[]> } or implement errorMapper.

Errors show on the wrong field (nested/array forms).

Likely cause: Error keys do not match RHF field paths.

Quick fix: Use RHF paths like address.city and items.0.price in server error keys.

Submit button enables too early and allows double submits.

Likely cause: UI is using isSubmitting instead of isPending.

Quick fix: Disable by formState.isPending for end-to-end submit state.

Old values keep returning in edit forms.

Likely cause: persistKey restored an old draft and overrode defaults.

Quick fix: Scope persistKey per entity and clear persisted drafts on load/success.

optimistic is undefined or has no effect.

Likely cause: Incomplete optimistic setup or UI is rendering confirmed data only.

Quick fix: Provide optimisticKey + optimisticData and render optimistic.data while pending.

File upload fails or file is empty on server.

Likely cause: Using JSON flow for file input instead of FormData action handling.

Quick fix: Use a FormData-based action and validate file type/size server-side.

onError does not fire when the form is invalid.

Likely cause: Invalid client form never reaches action execution.

Quick fix: Use formState.errors for client invalid state; onError handles action failure paths.

Standalone flow expects formAction but it does not exist.

Likely cause: Standalone API signature differs from Next.js adapter.

Quick fix: Use submit in options and trigger with handleSubmit().

60-second checklist

  1. 1.Confirm package choice: next adapter vs standalone adapter.
  2. 2.Confirm schema and validationMode match your intended UX.
  3. 3.Confirm action return shape for field errors.
  4. 4.Confirm field names and error keys use identical RHF paths.
  5. 5.Confirm submit buttons are gated by isPending.
  6. 6.Confirm persistKey scope and clear strategy.
  7. 7.Confirm optimistic settings and rendering path.
  8. 8.Confirm file flows use FormData, not JSON.