Troubleshooting
Find the symptom, read the cause, apply the fix.
Validation and errors
No error appears while I type
Cause. By design. input events do not validate until the field already has an error. A field validates when the user leaves it or commits a value.
Fix. To validate while typing, set validateOn: { input: true } on the field. See Validation.
An error does not clear after I fix the value
Cause. The field is in validationMode: 'lazy' and the event that would clear it is not enabled, or the error is not at this field's exact path.
Fix. Use the default eager mode, or enable the event. Confirm the issue's path matches the field: a field shows only issues at its exact path.
Required fields say "expected string, received undefined"
Cause. The field has no entry in initialValues, so the schema receives undefined and reports its generic type message instead of your custom one.
Fix. Provide '', false, [], or another starting value for every bound field. See Binding inputs.
A cross-field error never shows
Cause. The issue has no path, or the path names a different field. The error is then form-level, or shown by another field.
Fix. Report the issue on the field that should display it. See Cross-field validation.
A form-level error is not displayed anywhere
Cause. FieldError :errors="field" shows only issues at that field's own path. Issues without a path, or on a parent path, are in form.errors.
Fix. Render them from form.errors. See Errors.
A server error disappears when I tab away
Cause. Validating a field replaces the errors at its path. If the schema finds no problem there, the server error is dropped.
Fix. This is intended behavior. See Server errors if you need an error that outlives edits.
isValid is true on a form that is clearly invalid
Cause. isValid means "the error list is empty". Nothing has validated yet.
Fix. Call await form.validate() or submit. See Form state.
Submission
Submitting does nothing
Cause. Validation failed, and the failing field has no visible error. Typical reasons: the field is on another step or is hidden, the issue is form-level, or a required key was never given a value.
Fix. Inspect form.errors:
<template>
<pre>{{ form.errors }}</pre>
</template>
The second click on submit is ignored
Cause. A submit is already running. Extra submits are ignored until it finishes.
Fix. Disable the button with form.isSubmitting.
My onSubmit data does not match form.values
Cause. onSubmit receives the schema output, and form.values holds the input. Transforms, defaults, and coercions make them differ.
Fix. See Schema input and output.
An error in onSubmit shows nothing in the UI
Cause. Errors thrown by onSubmit are not turned into form errors. They go to Vue's error handler.
Fix. Catch expected failures and call form.setError. See Submission and reset.
The Reset button does not clear the inputs
Cause. Reset restores the baseline, not blank values. Or the button is outside Form, so no handler is attached.
Fix. Keep type="reset" inside <Form>, or call form.reset(). To clear a form that holds loaded data, call form.reset(blankValues) with explicit blank values, such as { name: '', email: '' }, which also makes them the new baseline.
Fields
My field config is ignored
Cause. Fields are cached by path and the config is read on the first call. A call without config, such as one in the template, may have created the field first.
Fix. Create each configured field once, in <script setup>, and reuse that instance. See Validation.
A Vue error says field is a required prop or path is unknown
Cause. You are using v3 syntax, such as <Field path="email">, with v4.
Fix. Pass an instance: <Field :field="form.field('email')">. See the v3 migration guide.
Typing a number gives me a string
Cause. Native inputs produce strings. v-model.number converts, but an empty input produces ''.
Fix. Use v-model.number with a number schema, or keep strings in the form and convert in the schema. See Binding inputs.
field.id breaks my HTML id
Cause. field.id is a symbol for Vue keys, not a string.
Fix. Use field.path for HTML ids and labels.
I get a TypeScript error on form.field('...')
Cause. The path is not in the schema's input shape. Check spelling, nesting, and whether the key is optional or renamed by a transform.
Fix. See TypeScript. The error is NotForm telling you the path does not exist.
Array fields
Items lose focus or show the wrong state after reordering
Cause. The list is keyed by index.
Fix. Key by item.id. See Array fields.
Errors or touched state land on the wrong item
Cause. The array was changed with push, splice, or sort on form.values instead of the array methods.
Fix. Use append, insert, remove, move, swap, and update.
Removing the last item leaves an error
Cause. The array's schema rule, such as .min(1), reports an issue on the array's own path.
Fix. That is intended. Show it with <FieldError :errors="arrayField" />.
Nuxt
Components or useForm are not found
Cause. The module is not registered, or the dev server was not restarted, or another component or composable has the same name.
Fix. Check modules: ['@notform/nuxt'], restart, and add an alias if there is a conflict. See Nuxt module.
I cannot import types from notform
Cause. Strict package managers do not expose a module's own dependencies.
Fix. Add notform as a direct dependency.
Performance
Validation feels slow, or my API is called too often
Cause. Each field validation runs the whole schema, including any async rules.
Fix. Add a debounce to the field that owns the slow rule, and cache lookups. See Async validation.
Still stuck?
Open an issue on the NotForm repository. Include your schema, the form setup, and the behavior you see.