This documentation is for a legacy version of Next.js and Supabase. For the latest version, please visit the Next.js and Supabase V2 documentation

How to handle errors in Server Actions

Learn how to handle errors in Server Actions in Makerkit.

Generally speaking, you can handle Server Action in three ways:

  1. You can use the try/catch block to catch errors and handle them in the catch block.
  2. You can use a React ErrorBoundary component to catch errors
  3. You can also use the special error.tsx file to handle errors at layout level.

Handling errors from a Server Action invoked by a Form

Let's assume we have a Form using a server action that throws an error:

async function serverActionWithError() {
'use server';
throw new Error(`This is error is in the Server Action`);
}
function FormWithServerAction() {
return (
<form action={serverActionWithError}>
<button>Submit Form</button>
</form>
);
}
export default FormWithServerAction;

We can wrap our form using the ErrorBoundary component we have at ~/core/ui/ErrorBoundary, and handle the error from there:

import ErrorBoundary from '~/core/ui/ErrorBoundary';
import FormWithServerAction from './Form';
function FormWithErrorBoundary() {
return (
<ErrorBoundary fallback={<p>Something went wrong</p>}>
<FormWithServerAction />
</ErrorBoundary>
);
}

If you click on the button, you'll see the error message rendered.

Handling errors from an imperatively invoked Server Action

If you are invoking a Server Action imperatively, we can wrap the useTransition hook in a try/catch block, and handle the error from there.

Let's assume we have a Server Action that throws an error:

'use server';
export async function serverActionWithError() {
throw new Error(`This is error is in the Server Action`);
}

We can invoke it imperatively from a client component, and handle the error from there:

'use client';
import { useTransition } from 'react';
import { serverActionWithError } from './actions';
function ImperativeServerAction() {
const [pending, startTransition] = useTransition();
return (
<button
disabled={pending}
onClick={() => {
startTransition(async () => {
try {
await serverActionWithError()
} catch (e) {
alert('error');
}
});
}}
>
Click Button
</button>
);
}
export default ImperativeServerAction;

If you click on the button, you'll see the alert popup with the error message.