Skip to content

docs: error boundary tutorial #893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
import FlakyComponent from './FlakyComponent.svelte';
</script>

<FlakyComponent />
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script>
let mouse = $state({ x: 0, y: 0 });
</script>

<svelte:window
onmousemove={(e) => {
mouse.x = e.clientX;
mouse.y = e.clientY;
}}
/>

<p>{mouse.x}x{mouse.y}</p>

<button onclick={() => mouse = null}>
whatever you do, don't click this button
</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script>
import FlakyComponent from './FlakyComponent.svelte';
</script>


<svelte:boundary onerror={(e) => console.error(e)}>
<FlakyComponent />

{#snippet failed(error, reset)}
<p>Oops! {error.message}</p>
<button onclick={reset}>Reset</button>
{/snippet}
</svelte:boundary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: <svelte:boundary>
---

To prevent errors from leaving your app in a broken state, you can contain them inside an _error boundary_ using the `<svelte:boundary>` element.

In this example, `<FlakyComponent>` contains a bug — clicking the button will set `mouse` to `null`, meaning that the `{mouse.x}` and `{mouse.y}` expressions in the template will fail to render.

In an ideal world we'd simply fix the bug. But that's not always an option — sometimes the component belongs to someone else, and sometimes you just need to guard against the unexpected. Begin by wrapping `<FlakyComponent />` with `<svelte:boundary>`:

```svelte
<!--- file: App.svelte --->
+++<svelte:boundary>+++
<FlakyComponent />
+++</svelte:boundary>+++
```

So far, nothing has changed, because the boundary doesn't specify a handler. Add a `failed` [snippet](snippets-and-render-tags) to provide some UI to show when an error occurs:

```svelte
<!--- file: App.svelte --->
<svelte:boundary>
<FlakyComponent />

+++ {#snippet failed(error)}
<p>Oops! {error.message}</p>
{/snippet}+++
</svelte:boundary>
```

Now, when we click the button, the contents of the boundary are replaced with the snippet. We can attempt to reset things by making use of the second argument passed to `failed`:

```svelte
<!--- file: App.svelte --->
<svelte:boundary>
<FlakyComponent />

{#snippet failed(error+++, reset+++)}
<p>Oops! {error.message}</p>
+++<button onclick={reset}>Reset</button>+++
{/snippet}
</svelte:boundary>
```

We can also specify an `onerror` handler, which is called with the same arguments passed to the `failed` snippet:

```svelte
<!--- file: App.svelte --->
<svelte:boundary +++onerror={(e) => console.error(e)}+++>
<FlakyComponent />

{#snippet failed(error, reset)}
<p>Oops! {error.message}</p>
<button onclick={reset}>Reset</button>
{/snippet}
</svelte:boundary>
```

This is useful for sending information about the error to a reporting service, or adding UI outside the error boundary itself.
2 changes: 1 addition & 1 deletion apps/svelte.dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"prettier-plugin-svelte": "^3.2.4",
"satori": "^0.10.13",
"satori-html": "^0.3.2",
"svelte": "5.1.11",
"svelte": "5.3.0",
"svelte-check": "^4.0.0",
"svelte-preprocess": "^5.1.4",
"tiny-glob": "^0.2.9",
Expand Down
Loading