diff --git a/.changeset/slimy-turtles-yell.md b/.changeset/slimy-turtles-yell.md
new file mode 100644
index 0000000000..e3f3a66264
--- /dev/null
+++ b/.changeset/slimy-turtles-yell.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: flush pending changes after rendering `failed` snippet
diff --git a/packages/svelte/src/internal/client/dom/blocks/boundary.js b/packages/svelte/src/internal/client/dom/blocks/boundary.js
index 3da9204571..72e64b1a3a 100644
--- a/packages/svelte/src/internal/client/dom/blocks/boundary.js
+++ b/packages/svelte/src/internal/client/dom/blocks/boundary.js
@@ -30,7 +30,6 @@ import {
skip_nodes,
set_hydrate_node
} from '../hydration.js';
-import { get_next_sibling } from '../operations.js';
import { queue_micro_task } from '../task.js';
import * as e from '../../errors.js';
import * as w from '../../warnings.js';
@@ -402,6 +401,7 @@ export class Boundary {
if (failed) {
queue_micro_task(() => {
this.#failed_effect = this.#run(() => {
+ Batch.ensure();
this.#is_creating_fallback = true;
try {
diff --git a/packages/svelte/tests/runtime-runes/samples/error-boundary-23/_config.js b/packages/svelte/tests/runtime-runes/samples/error-boundary-23/_config.js
new file mode 100644
index 0000000000..7a6a66eb66
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/error-boundary-23/_config.js
@@ -0,0 +1,12 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ async test({ assert, target, logs }) {
+ const btn = target.querySelector('button');
+ btn?.click();
+ await tick();
+
+ assert.deepEqual(logs, ['attachment']);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/error-boundary-23/main.svelte b/packages/svelte/tests/runtime-runes/samples/error-boundary-23/main.svelte
new file mode 100644
index 0000000000..c1fe20d931
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/error-boundary-23/main.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {fail ? error() : 'all good'}
+
+
+ {#snippet failed()}
+ oops!
+ {/snippet}
+