install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/svelte-error-pages" ~/.claude/skills/intense-visions-harness-engineering-svelte-error-pages && rm -rf "$T"
manifest:
agents/skills/claude-code/svelte-error-pages/SKILL.mdsource content
Svelte Error Pages
Handle 404s, auth failures, and unexpected crashes in SvelteKit with +error.svelte, the error() helper, and handleError hooks
When to Use
- You need to show a custom error page for 404s, 403s, or other HTTP errors thrown in load functions
- You want to customize the error UI per route segment (nested error boundaries)
- You need to capture unexpected server errors and report them to an error tracking service
- You are unsure when to use
vs. throwing raw errors vs. returningerror()fail()
Instructions
Defining error pages:
- Create
in any route directory. It catches errors thrown by the load functions in that route segment and all its children:+error.svelte
<!-- src/routes/+error.svelte — global error boundary --> <script lang="ts"> import { page } from '$app/stores' </script> <h1>{$page.status}: {$page.error?.message}</h1> {#if $page.status === 404} <p>This page doesn't exist.</p> <a href="/">Go home</a> {:else} <p>Something went wrong. Please try again.</p> {/if}
- Add nested
files for section-specific error UIs. The nearest ancestor+error.svelte
catches the error:+error.svelte
routes/ +error.svelte → global fallback blog/ +error.svelte → blog-specific errors [slug]/ +page.server.ts → throws error(404) → caught by blog/+error.svelte
Throwing expected errors:
- Use the
helper fromerror
for expected, anticipated errors (404, 401, 403). These are shown to the user via@sveltejs/kit
:+error.svelte
// +page.server.ts import { error } from '@sveltejs/kit'; export const load: PageServerLoad = async ({ params }) => { const post = await db.post.findUnique({ where: { slug: params.slug } }); if (!post) throw error(404, 'Post not found'); if (!post.published) throw error(403, 'This post is not published'); return { post }; };
- Pass a structured message object instead of a string for richer error data:
throw error(422, { message: 'Validation failed', field: 'email' });
Access in
+error.svelte:
<p>{$page.error?.message}</p>
Unexpected errors:
- Unhandled exceptions (thrown objects that are not SvelteKit errors) are treated as 500 errors. SvelteKit will NOT expose the error message to the client — only the
hook's return value is shown:handleError
// This exception message is NEVER shown to users throw new Error('Database connection string exposed!'); // handleError in hooks.server.ts controls what users see: export const handleError: HandleServerError = ({ error }) => { return { message: 'An internal error occurred. Please try again.' }; };
Redirecting from error pages:
- Throw
fromredirect
to navigate the user rather than showing an error:@sveltejs/kit
import { redirect } from '@sveltejs/kit'; export const load: PageServerLoad = async ({ locals }) => { if (!locals.user) redirect(303, '/login'); return { user: locals.user }; };
Custom error shape:
- Extend the
interface to add fields toApp.Error
:$page.error
// src/app.d.ts declare global { namespace App { interface Error { message: string; errorId?: string; code?: string; } } }
// hooks.server.ts export const handleError: HandleServerError = async ({ error, status }) => { const errorId = crypto.randomUUID(); await reportError(error, errorId); return { message: status === 404 ? 'Page not found' : 'Something went wrong', errorId, }; };
<!-- +error.svelte --> {#if $page.error?.errorId} <small>Error ID: {$page.error.errorId}</small> {/if}
Details
Expected vs. unexpected errors:
| Type | How thrown | User sees | Logged |
|---|---|---|---|
| Expected | | The message directly | No (by design) |
| Unexpected | | return value | Yes (via ) |
| Redirect | | Navigation | No |
error() vs. fail():
— terminates the load function, shows theerror()
page+error.svelte
— only valid in form actions, re-renders the page with error data in thefail()
propform
Never use
fail() in load functions; never use error() in actions when you want to re-display the form.
Layout-level errors:
If an error is thrown in a layout load function, the nearest ancestor
+error.svelte catches it — not a sibling of the layout. This means errors in (app)/+layout.server.ts render the (app)/+error.svelte, not the root +error.svelte.
The root error page:
The root
src/routes/+error.svelte is the last resort. If this page itself throws an error, SvelteKit falls back to a static error page generated from src/error.html (if it exists) or a plain text response.
$page.status:
The
$page.status reactive value reflects the HTTP status code of the current page, including error pages. Use it to render different UI for 404 vs. 500 errors.
Source
https://kit.svelte.dev/docs/errors
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.