Skip to content

Async derived rejection escapes inner boundary #18383

Description

@johnathanludwig

Describe the bug

Looks like this was introduced in 5.55.6.

Used claude for the research/repro:

When an async $derived rejects inside a svelte:boundary that handles the error (via failed and/or onerror), the error is delivered twice. The first delivery is handled correctly — the boundary tears down its main effect and renders the failed snippet. But a follow-up settle then re-runs the reaction (finish in reactivity/async.js), which synchronously re-throws the rejected value and routes it through invoke_error_boundary(error, parent). By then the handling boundary's effect has been destroyed, so effect.b is null, and invoke_error_boundary crashes at:

// packages/svelte/src/internal/client/error-handling.js
/** @type {Boundary} */ (effect.b).error(error); // effect.b is null

with TypeError: Cannot read properties of null (reading 'error'). That secondary error has no live boundary to catch it, so it escapes to the parent boundary — i.e. a child component's localized error takes down a much larger part of the tree.

A dependent $derived that reads the awaited value (const model = $derived({ title: data.title })) is what triggers the re-run; without the second read the reaction has nothing to re-evaluate.

Reproduction

https://svelte.dev/playground/ab1d596e8f5f45ebb7f844db875fe56b?version=5.55.6

Not fixed in 5.56.2 https://svelte.dev/playground/ab1d596e8f5f45ebb7f844db875fe56b?version=5.56.2

Works in 5.55.5 https://svelte.dev/playground/ab1d596e8f5f45ebb7f844db875fe56b?version=5.55.5

Logs

System Info

svelte: 5.55.10
@sveltejs/kit: 2.61.1

Severity

blocking an upgrade

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions