This makes error boundaries run on the server if a new `onerror` handler
is passed to `render`. `onerror` can either synchronously or
asynchronously return a value. It should be a sanitized
JSON.stringify-able value so that it can be passed to the client for
hydration via a comment. `mount/hydrate` also get the `onerror`
property.
If no `onerror` is passed to `render` it will just throw just like
before, hence this is backwards compatible.
This work is important for SvelteKit to allow `+error.svelte` to make
use of them and in general to make boundaries properly work during SSR
(also see https://github.com/sveltejs/kit/issues/14398).
closes#15370
### Before submitting the PR, please make sure you do the following
- [x] It's really useful if your PR references an issue where it is
discussed ahead of time. In many cases, features are absent for a
reason. For large changes, please create an RFC:
https://github.com/sveltejs/rfcs
- [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`.
- [x] This message body should clearly illustrate what problems it
solves.
- [x] Ideally, include a test that fails without this PR but passes with
it.
- [x] If this PR changes code within `packages/svelte/src`, add a
changeset (`npx changeset`).
### Tests and linting
- [x] Run the tests with `pnpm test` and lint the project with `pnpm
lint`
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
@ -102,3 +102,40 @@ If an `onerror` function is provided, it will be called with the same two `error
```
If an error occurs inside the `onerror` function (or if you rethrow the error), it will be handled by a parent boundary if such exists.
## Using `transformError`
By default, error boundaries have no effect on the server — if an error occurs during rendering, the render as a whole will fail.
Since 5.51 you can control this behaviour for boundaries with a `failed` snippet, by calling [`render(...)`](imperative-component-api#render) with a `transformError` function.
> [!NOTE] If you're using Svelte via a framework such as SvelteKit, you most likely don't have direct access to the `render(...)` call — the framework must configure `transformError` on your behalf. SvelteKit will add support for this in the near future, via the [`handleError`](../kit/hooks#Shared-hooks-handleError) hook.
The `transformError` function must return a JSON-stringifiable object which will be used to render the `failed` snippet. This object will be serialized and used to hydrate the snippet in the browser:
```js
// @errors: 1005
import { render } from 'svelte/server';
import App from './App.svelte';
const { head, body } = await render(App, {
transformError: (error) => {
// log the original error, with the stack trace...
console.error(error);
// ...and return a sanitized user-friendly error
// to display in the `failed` snippet
return {
message: 'An error occurred!'
};
};
});
```
If `transformError` throws (or rethrows) an error, `render(...)` as a whole will fail with that error.
> [!NOTE] Errors that occur during server-side rendering can contain sensitive information in the `message` and `stack`. It's recommended to redact these rather than sending them unaltered to the browser.
If the boundary has an `onerror` handler, it will be called upon hydration with the deserialized error object.
The [`mount`](imperative-component-api#mount) and [`hydrate`](imperative-component-api#hydrate) functions also accept a `transformError` option, which defaults to the identity function. As with `render`, this function transforms a render-time error before it is passed to a `failed` snippet or `onerror` handler.