Error Handling
Development
One of the advantages to working with a robust server-side framework is the built-in exception handling you get for free. For example, Laravel ships with Ignition, a beautiful error reporting tool which displays a nicely formatted stack trace in local development.
The challenge is, if you’re making an XHR request (which Inertia does) and you hit a server-side error, you’re typically left digging through the network tab in your browser’s devtools to diagnose the problem.
Inertia solves this issue by showing all non-Inertia responses in a modal. This means you get the same beautiful error-reporting you’re accustomed to, even though you’ve made that request over XHR.
Production
In production you will want to return a proper Inertia error response instead of relying on the modal-driven error reporting that is present during development. To accomplish this, you’ll need to update your framework’s default exception handler to return a custom error page.
When building Laravel applications, you can accomplish this by using the respond exception method in your application’s bootstrap/app.php file.
using InertiaCore;using Microsoft.AspNetCore.Mvc;
if (!app.Environment.IsDevelopment()){ app.UseExceptionHandler("/Error/500"); app.UseStatusCodePagesWithReExecute("/Error/{0}");}
public class ErrorController : Controller{ [Route("Error/{statusCode:int}")] public IActionResult Handle(int statusCode) { if (new[] { 500, 503, 404, 403 }.Contains(statusCode)) { HttpContext.Response.StatusCode = statusCode; return Inertia.Render("Error", new { Status = statusCode }); }
return StatusCode(statusCode); }}use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response;use Inertia\Inertia;
->withExceptions(function (Exceptions $exceptions) { $exceptions->respond(function (Response $response, Throwable $exception, Request $request) { if (! app()->environment(['local', 'testing']) && in_array($response->getStatusCode(), [500, 503, 404, 403])) { return Inertia::render('Error', ['status' => $response->getStatusCode()]) ->toResponse($request) ->setStatusCode($response->getStatusCode()); } elseif ($response->getStatusCode() === 419) { return back()->with([ 'message' => 'The page expired, please try again.', ]); }
return $response; });})You may have noticed we’re returning an Error page component in the example above. You’ll need to actually create this component, which will serve as the generic error page for your application. Here’s an example error component you can use as a starting point.
<template> <div> <H1>{{ title }}</H1> <div>{{ description }}</div> </div></template>
<script>export default { props: { status: Number, }, computed: { title() { return { 503: '503: Service Unavailable', 500: '500: Server Error', 404: '404: Page Not Found', 403: '403: Forbidden', }[this.status] }, description() { return { 503: 'Sorry, we are doing some maintenance. Please check back soon.', 500: 'Whoops, something went wrong on our servers.', 404: 'Sorry, the page you are looking for could not be found.', 403: 'Sorry, you are forbidden from accessing this page.', }[this.status] }, },}</script><script setup>import { computed } from 'vue'
const props = defineProps({ status: Number })
const title = computed(() => { return { 503: '503: Service Unavailable', 500: '500: Server Error', 404: '404: Page Not Found', 403: '403: Forbidden', }[props.status]})
const description = computed(() => { return { 503: 'Sorry, we are doing some maintenance. Please check back soon.', 500: 'Whoops, something went wrong on our servers.', 404: 'Sorry, the page you are looking for could not be found.', 403: 'Sorry, you are forbidden from accessing this page.', }[props.status]})</script>
<template> <div> <H1>{{ title }}</H1> <div>{{ description }}</div> </div></template>export default function ErrorPage({ status }) { const title = { 503: '503: Service Unavailable', 500: '500: Server Error', 404: '404: Page Not Found', 403: '403: Forbidden', }[status]
const description = { 503: 'Sorry, we are doing some maintenance. Please check back soon.', 500: 'Whoops, something went wrong on our servers.', 404: 'Sorry, the page you are looking for could not be found.', 403: 'Sorry, you are forbidden from accessing this page.', }[status]
return ( <div> <H1>{title}</H1> <div>{description}</div> </div> )}<script> export let status
$: title = { 503: '503: Service Unavailable', 500: '500: Server Error', 404: '404: Page Not Found', 403: '403: Forbidden', }[status]
$: description = { 503: 'Sorry, we are doing some maintenance. Please check back soon.', 500: 'Whoops, something went wrong on our servers.', 404: 'Sorry, the page you are looking for could not be found.', 403: 'Sorry, you are forbidden from accessing this page.', }[status]</script>
<div> <H1>{title}</H1> <div>{description}</div></div>