diff --git a/.changeset/pink-doors-chew.md b/.changeset/pink-doors-chew.md
new file mode 100644
index 0000000000..ea43c5e00c
--- /dev/null
+++ b/.changeset/pink-doors-chew.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: restore active reaction if then block throws
diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js
index 3c6bc9900d..29ef15452f 100644
--- a/packages/svelte/src/internal/client/dom/blocks/await.js
+++ b/packages/svelte/src/internal/client/dom/blocks/await.js
@@ -70,42 +70,44 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
if (DEV) set_dev_current_component_function(component_function);
}
- if (state === PENDING && pending_fn) {
- if (pending_effect) resume_effect(pending_effect);
- else pending_effect = branch(() => pending_fn(anchor));
- }
-
- if (state === THEN && then_fn) {
- if (then_effect) resume_effect(then_effect);
- else then_effect = branch(() => then_fn(anchor, input_source));
- }
+ try {
+ if (state === PENDING && pending_fn) {
+ if (pending_effect) resume_effect(pending_effect);
+ else pending_effect = branch(() => pending_fn(anchor));
+ }
- if (state === CATCH && catch_fn) {
- if (catch_effect) resume_effect(catch_effect);
- else catch_effect = branch(() => catch_fn(anchor, error_source));
- }
+ if (state === THEN && then_fn) {
+ if (then_effect) resume_effect(then_effect);
+ else then_effect = branch(() => then_fn(anchor, input_source));
+ }
- if (state !== PENDING && pending_effect) {
- pause_effect(pending_effect, () => (pending_effect = null));
- }
+ if (state === CATCH && catch_fn) {
+ if (catch_effect) resume_effect(catch_effect);
+ else catch_effect = branch(() => catch_fn(anchor, error_source));
+ }
- if (state !== THEN && then_effect) {
- pause_effect(then_effect, () => (then_effect = null));
- }
+ if (state !== PENDING && pending_effect) {
+ pause_effect(pending_effect, () => (pending_effect = null));
+ }
- if (state !== CATCH && catch_effect) {
- pause_effect(catch_effect, () => (catch_effect = null));
- }
+ if (state !== THEN && then_effect) {
+ pause_effect(then_effect, () => (then_effect = null));
+ }
- if (restore) {
- if (DEV) set_dev_current_component_function(null);
- set_component_context(null);
- set_active_reaction(null);
- set_active_effect(null);
-
- // without this, the DOM does not update until two ticks after the promise
- // resolves, which is unexpected behaviour (and somewhat irksome to test)
- flush_sync();
+ if (state !== CATCH && catch_effect) {
+ pause_effect(catch_effect, () => (catch_effect = null));
+ }
+ } finally {
+ if (restore) {
+ if (DEV) set_dev_current_component_function(null);
+ set_component_context(null);
+ set_active_reaction(null);
+ set_active_effect(null);
+
+ // without this, the DOM does not update until two ticks after the promise
+ // resolves, which is unexpected behaviour (and somewhat irksome to test)
+ flush_sync();
+ }
}
}
diff --git a/packages/svelte/tests/runtime-runes/samples/await-render-error-restore-reaction/_config.js b/packages/svelte/tests/runtime-runes/samples/await-render-error-restore-reaction/_config.js
new file mode 100644
index 0000000000..5cae253851
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/await-render-error-restore-reaction/_config.js
@@ -0,0 +1,16 @@
+import { ok, test } from '../../test';
+import { flushSync } from 'svelte';
+
+export default test({
+ compileOptions: {
+ dev: true
+ },
+ async test({ target, errors, assert, window }) {
+ const btn = target.querySelector('button');
+ ok(btn);
+ flushSync(() => {
+ btn.click();
+ });
+ assert.deepEqual(errors, []);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/await-render-error-restore-reaction/main.svelte b/packages/svelte/tests/runtime-runes/samples/await-render-error-restore-reaction/main.svelte
new file mode 100644
index 0000000000..4e9e32dcab
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/await-render-error-restore-reaction/main.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+{#await Promise.resolve() then}
+ {err.or}
+{/await}
\ No newline at end of file