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.
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.
Dialog element
By default, Inertia < 3.x displays error modals using a custom <div> overlay. However, you can opt-in to using the native HTML <dialog> element instead, which provides built-in modal functionality including backdrop handling.
To enable this, configure the future.useDialogForErrorModal option in your application defaults.
createInertiaApp({
// resolve, setup, etc.
defaults: {
future: {
useDialogForErrorModal: true,
},
},
})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, use the rescue_from method in your ApplicationController.
class ApplicationController < ActionController::Base
rescue_from StandardError, with: :inertia_error_page
private
def inertia_error_page(exception)
raise exception if Rails.env.local?
status = ActionDispatch::ExceptionWrapper.new(nil, exception).status_code
render inertia: 'ErrorPage', props: { status: }, status:
end
endSince rescue_from runs inside the controller, shared data defined via inertia_share is available automatically.
Error Page Example
You'll need to create the error page components referenced above. Here's an example you may use as a starting point.
<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>Routing-level exceptions
Some exceptions (for example, routing 404s) occur before a controller is instantiated, so rescue_from won't catch them. Rails handles these via static files in public/ by default, which is fine for most apps.
If you want routing-level errors to render as Inertia pages too, point exceptions_app at your router and add error routes.
# config/application.rb
config.exceptions_app = routes# config/routes.rb
match '/404', to: 'errors#show', defaults: { status: 404 }, via: :all
match '/422', to: 'errors#show', defaults: { status: 422 }, via: :all
match '/500', to: 'errors#show', defaults: { status: 500 }, via: :all# app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
def show
status = params[:status].to_i
render inertia: 'ErrorPage', props: { status: }, status:
end
endSince this goes through the full Rails stack, shared data from inertia_share is available on error pages as well.