Errors are an inevitable fact of software development. SvelteKit handles errors differently depending on where they occur, what kind of errors they are, and the nature of the incoming request. ## Error objects Every error passes through the [`handleError`](hooks#handleError) hook — which can log it and customise it — before it is rendered. The hook's `kind` property identifies where the error came from: your app (`'app'`), SvelteKit (`'framework'`), validation of a [remote function](remote-functions) argument (`'validation'`) or an unknown source (`'unknown'`). By default, all are represented as simple `{ status: number, message: string }` objects. You can add additional properties, like a `code` or a tracking `id`, as shown in the examples below. (When using TypeScript this requires you to redefine the `Error` type as described in [Type safety](errors#Type-safety) below). ## App errors An app error is one thrown from your app code using the [`error`](@sveltejs-kit#error) function imported from `@sveltejs/kit`: ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare module '#lib/server/database.js' { export function getPost(slug: string): Promise<{ title: string, content: string } | undefined> } // @filename: index.js // ---cut--- import { error } from '@sveltejs/kit'; import * as db from '#lib/server/database.js'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { const post = await db.getPost(params.slug); if (!post) { error(404, 'Not found'); } return { post }; } ``` This throws an exception that SvelteKit catches, causing it to set the response status code to 404 and render an [`+error.svelte`](routing#error) component, where the `error` is an `App.Error` object with the provided `status` and `message`. On its way there, the error passes through the [`handleError`](hooks#handleError) hook with `kind: 'app'`. Since the shape of the error is determined by your app, it is considered safe to expose, and the hook can pass it through unchanged. ```svelte

{error.message}

``` You can add extra properties to the error object if needed: ```js // @filename: ambient.d.ts declare global { namespace App { interface Error { message: string; code: string; } } } export {} // @filename: index.js import { error } from '@sveltejs/kit'; // ---cut--- error(404, 'Not found', { +++code: 'NOT_FOUND'+++ }); ``` > [!NOTE] [In SvelteKit 1.x](migrating-to-sveltekit-2#redirect-and-error-are-no-longer-thrown-by-you) you had to `throw` the `error` yourself ## Framework errors Some errors are generated by SvelteKit itself rather than by your code — a request that doesn't match any route (404), a `POST` request to a page without actions (405), a request body that exceeds the size limit (413), and so on. These also go through `handleError`, with `kind: 'framework'`. The `error` you receive is a `{ status, message }` object whose `message` is a terse but safe description of what went wrong, such as `'Not Found'`, so it can be exposed to users as-is. If you log errors inside `handleError`, remember that framework errors such as 404s are routine — you will generally want to avoid logging them. ## Validation errors Validation errors occur when a [remote function](remote-functions) is called with invalid data. When these are passed to `handleError`, they are accompanied by an array of `issues`. See [Handling validation errors](remote-functions#Handling-validation-errors) for more details. ## Unknown errors An _unknown_ error is any other exception that occurs while handling a request. Since these can contain sensitive information, unknown error messages and stack traces are not exposed to users. By default, unknown errors are printed to the console (or, in production, your server logs), while the error that is exposed to the user has a generic shape: ```json { "status": 500, "message": "Internal Error" } ``` Unknown errors go through the [`handleError`](hooks#handleError) hook with `kind: 'unknown'`, because SvelteKit does not know what went wrong. There you can add your own error handling, for example sending errors to a reporting service, or returning a custom error object which becomes the `error` prop passed to `+error.svelte`. The value you receive is the raw thrown value, and nothing about it is exposed unless you choose to expose it. Anything you return overrides the defaults, so you can — for example — use the type of the thrown error to determine the HTTP status code used in the response: ```js /// file: src/hooks.server.js // Assuming you have this ... class NotFound extends Error {} /** @type {import('@sveltejs/kit/hooks').HandleServerError} */ export function handleError({ kind, error, event }) { if (kind === 'unknown') { // ... you can do this if (error instanceof NotFound) { return { status: 404, message: 'Not found' }; } return { message: 'Something went wrong' }; } // app and framework errors are already safe to expose return error; } ``` ## Error boundaries Errors that occur during `load` or rendering (for example inside a component's `