Skip to content

Docs: Add error handling section to submission handling docs #1566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions docs/framework/react/guides/submission-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,83 @@ id: submission-handling
title: Submission handling
---

## Error handling

When a user submits a form, there are several ways errors can occur — each requiring its own handling approach. TanStack Form gives you the flexibility to handle errors your way. To help you get started, here’s how to approach the three most common types of errors you’ll run into:

- **Synchronous user errors** – Things you can catch right away, like a field being left empty or text that's too short.
- **Asynchronous user errors** – Issues that come up after submission, like finding out a username is already taken.
- **Server errors** – Unexpected problems on the backend, such as a failed request or an unknown error.

> [!TIP]
> If you need help understanding how validation works in TanStack Form, be sure to check out the [form validation](./validation.md) guide!

### Synchronous user errors

These are validation issues that can be detected immediately on the client side, even before the form is submitted. They are typically managed using both form-level and field-level validators, as shown in the example below:

```tsx
<form.Field
name="age"
validators={{
onChange: ({ value }) =>
value < 13 ? 'You must be 13 to make an account' : undefined,
}}
children={{() => <>{/* ... */}</>}}
/>
```

### Asynchronous user errors

Asynchronous errors usually occur after the form is submitted, often due to external checks — like verifying whether a username or email is already taken. These kinds of errors can be handled using the async variants of form and field validators.

Since these requests are usually at form level, see how you can [set field-level errors from the form's validators](./validation.md).

```tsx
const form = useForm({
// ...
validators: {
onSubmitAsync: async ({ value }) => {
// Validate the value on the server
const response = await createAccount(value)

if (response.isError) {
// Username is taken, return an error for the username field
return {
fields: {
username: response.message,
},
}
}
// The account creation was a success. There is no error that needs to be shown.
return null
},
},
})
```

### Server errors

Server errors are unexpected failures that happen during submission — like connectivity issues or internal server faults. These aren't related to user input and therefore **should not be part of form validation**.

These kinds of errors are typically handled by an external library, such as `TanStack Query`:

```tsx
// Using TanStack Query for data mutations
const createAccountMutation = useMutation({
/* ... */
})

const form = useForm({
// ...
onSubmit: async ({ value }) => {
// If an error happens, they are accessible through
// `createAccountMutation.error`
await createAccountMutation.mutateAsync(value)
Copy link
Contributor

@Pascalmh Pascalmh Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promoting "mutateAsync" here feels off:

you should almost always use mutate
– https://tkdodo.eu/blog/mastering-mutations-in-react-query#mutate-or-mutateasync

Suggested change
await createAccountMutation.mutateAsync(value)
createAccountMutation.mutate(value, {
onSuccess: () => {
// handle success by navigate to another route e.g.
}
})

},
})
```

## Passing additional data to submission handling

You may have multiple types of submission behaviour, for example, going back to another page or staying on the form.
Expand Down
77 changes: 77 additions & 0 deletions docs/framework/solid/guides/submission-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,83 @@ id: submission-handling
title: Submission handling
---

## Error handling

When a user submits a form, there are several ways errors can occur — each requiring its own handling approach. TanStack Form gives you the flexibility to handle errors your way. To help you get started, here’s how to approach the three most common types of errors you’ll run into:

- **Synchronous user errors** – Things you can catch right away, like a field being left empty or text that's too short.
- **Asynchronous user errors** – Issues that come up after submission, like finding out a username is already taken.
- **Server errors** – Unexpected problems on the backend, such as a failed request or an unknown error.

> [!TIP]
> If you need help understanding how validation works in TanStack Form, be sure to check out the [form validation](./validation.md) guide!

### Synchronous user errors

These are validation issues that can be detected immediately on the client side, even before the form is submitted. They are typically managed using both form-level and field-level validators, as shown in the example below:

```tsx
<form.Field
name="age"
validators={{
onChange: ({ value }) =>
value < 13 ? 'You must be 13 to make an account' : undefined,
}}
>
{() => <>{/* ... */}</>}
</form.Field>
```

### Asynchronous user errors

Asynchronous errors usually occur after the form is submitted, often due to external checks — like verifying whether a username or email is already taken. These kinds of errors can be handled using the async variants of form and field validators.

Since these requests are usually at form level, see how you can [set field-level errors from the form's validators](./validation.md).

```tsx
const form = createForm(() => ({
// ...
validators: {
onSubmitAsync: async ({ value }) => {
// Validate the value on the server
const response = await createAccount(value)
if (response.isError) {
// Username is taken, return an error for the username field
return {
fields: {
username: response.message,
},
}
}
// The account creation was a success. There is no error that needs to be shown.
return null
},
},
}))
```

### Server errors

Server errors are unexpected failures that happen during submission — like connectivity issues or internal server faults. These aren't related to user input and therefore **should not be part of form validation**.

These kinds of errors are typically handled by an external library, such as `TanStack Query`:

```tsx
// Using TanStack Query for data mutations
const createAccountMutation = useMutation(() => ({
/* ... */
}))

const form = createForm(() => ({
// ...
onSubmit: async ({ value }) => {
// If an error happens, they are accessible through
// `createAccountMutation.error`
await createAccountMutation.mutateAsync(value)
},
}))
```

## Passing additional data to submission handling

You may have multiple types of submission behaviour, for example, going back to another page or staying on the form.
Expand Down
93 changes: 93 additions & 0 deletions docs/framework/vue/guides/submission-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,99 @@ id: submission-handling
title: Submission handling
---

## Error handling

When a user submits a form, there are several ways errors can occur — each requiring its own handling approach. TanStack Form gives you the flexibility to handle errors your way. To help you get started, here’s how to approach the three most common types of errors you’ll run into:

- **Synchronous user errors** – Things you can catch right away, like a field being left empty or text that's too short.
- **Asynchronous user errors** – Issues that come up after submission, like finding out a username is already taken.
- **Server errors** – Unexpected problems on the backend, such as a failed request or an unknown error.

> [!TIP]
> If you need help understanding how validation works in TanStack Form, be sure to check out the [form validation](./validation.md) guide!

### Synchronous user errors

These are validation issues that can be detected immediately on the client side, even before the form is submitted. They are typically managed using both form-level and field-level validators, as shown in the example below:

```vue
<template>
<!-- ... -->
<form.Field
name="age"
:validators="{
onChange: ({ value }) =>
value < 13 ? 'You must be 13 to make an account' : undefined,
}"
>
<template v-slot="{ field }">
<!-- ... -->
</template>
</form.Field>
<!-- ... -->
</template>
```

### Asynchronous user errors

Asynchronous errors usually occur after the form is submitted, often due to external checks — like verifying whether a username or email is already taken. These kinds of errors can be handled using the async variants of form and field validators.

Since these requests are usually at form level, see how you can [set field-level errors from the form's validators](./validation.md).

```vue
<script setup lang="ts">
// ...

const form = useForm({
// ...
validators: {
// Add validators to the form the same way you would add them to a field
onSubmitAsync: async ({ value }) => {
// Validate the value on the server
const response = await createAccount(value)

if (response.isError) {
// Username is taken, return an error for the username field
return {
fields: {
username: response.message,
},
}
}
// The account creation was a success. There is no error that needs to be shown.
return null
},
},
})
</script>
```

### Server errors

Server errors are unexpected failures that happen during submission — like connectivity issues or internal server faults. These aren't related to user input and therefore **should not be part of form validation**.

These kinds of errors are typically handled by an external library, such as `TanStack Query`:

```vue
<script setup lang="ts">
// ...

// Using TanStack Query for data mutations
const createAccountMutation = useMutation({
/* ... */
})

const form = useForm({
// ...
onSubmit: async ({ value }) => {
// If an error happens, they are accessible through
// `createAccountMutation.error`
await createAccountMutation.mutateAsync(value)
},
})
</script>
```

## Passing additional data to submission handling

You may have multiple types of submission behaviour, for example, going back to another page or staying on the form.
Expand Down