diff --git a/.changeset/true-pigs-go.md b/.changeset/true-pigs-go.md
new file mode 100644
index 0000000000..b4900b38fa
--- /dev/null
+++ b/.changeset/true-pigs-go.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: catch rejected promises while merging/committing
diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js
index b9721b6243..82c97cf95c 100644
--- a/packages/svelte/src/internal/client/reactivity/batch.js
+++ b/packages/svelte/src/internal/client/reactivity/batch.js
@@ -510,7 +510,7 @@ export class Batch {
for (const [effect, deferred] of batch.async_deriveds) {
const d = this.async_deriveds.get(effect);
- if (d) deferred.promise.then(d.resolve);
+ if (d) deferred.promise.then(d.resolve).catch(d.reject);
}
// Mark is not guaranteed not touch these, so we transfer them
@@ -677,7 +677,7 @@ export class Batch {
// immediately resolving them? Likely not because of how this.apply() works.
for (const [effect, deferred] of this.async_deriveds) {
const d = batch.async_deriveds.get(effect);
- if (d) deferred.promise.then(d.resolve);
+ if (d) deferred.promise.then(d.resolve).catch(d.reject);
}
}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-branch-merge-obsolete/_config.js b/packages/svelte/tests/runtime-runes/samples/async-branch-merge-obsolete/_config.js
new file mode 100644
index 0000000000..faf1ff7f6b
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-branch-merge-obsolete/_config.js
@@ -0,0 +1,17 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ async test({ assert, target }) {
+ await tick();
+ const [increment] = target.querySelectorAll('button');
+
+ increment.click();
+ await tick();
+ increment.click();
+ await tick();
+ increment.click();
+ await tick();
+ assert.htmlEqual(target.innerHTML, ' done');
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/async-branch-merge-obsolete/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-branch-merge-obsolete/main.svelte
new file mode 100644
index 0000000000..4780442293
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-branch-merge-obsolete/main.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+{#if count < 3}
+ {await push(count)}
+{:else}
+ done
+{/if}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-later-promise-fails-first/_config.js b/packages/svelte/tests/runtime-runes/samples/async-later-promise-fails-first/_config.js
new file mode 100644
index 0000000000..5e18c953c7
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-later-promise-fails-first/_config.js
@@ -0,0 +1,25 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ async test({ assert, target }) {
+ await tick();
+ const [increment, pop] = target.querySelectorAll('button');
+
+ increment.click();
+ await tick();
+ increment.click();
+ await tick();
+ increment.click();
+ await tick();
+ pop.click();
+ await tick();
+ assert.htmlEqual(target.innerHTML, ' failed');
+
+ pop.click();
+ await tick();
+ pop.click();
+ await tick();
+ assert.htmlEqual(target.innerHTML, ' failed');
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/async-later-promise-fails-first/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-later-promise-fails-first/main.svelte
new file mode 100644
index 0000000000..3293e4ab88
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-later-promise-fails-first/main.svelte
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ {await push(count)}
+
+ {#snippet failed()}failed{/snippet}
+