diff --git a/.changeset/old-crabs-dance.md b/.changeset/old-crabs-dance.md
new file mode 100644
index 0000000000..efb375aa2a
--- /dev/null
+++ b/.changeset/old-crabs-dance.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: ensure head effects are kept in the effect tree
diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-head.js b/packages/svelte/src/internal/client/dom/blocks/svelte-head.js
index 7c7eed24f7..7cab6c3385 100644
--- a/packages/svelte/src/internal/client/dom/blocks/svelte-head.js
+++ b/packages/svelte/src/internal/client/dom/blocks/svelte-head.js
@@ -2,7 +2,7 @@
import { hydrate_node, hydrating, set_hydrate_node, set_hydrating } from '../hydration.js';
import { create_text, get_first_child, get_next_sibling } from '../operations.js';
import { block } from '../../reactivity/effects.js';
-import { COMMENT_NODE, HEAD_EFFECT } from '#client/constants';
+import { COMMENT_NODE, EFFECT_PRESERVED, HEAD_EFFECT } from '#client/constants';
/**
* @param {string} hash
@@ -49,7 +49,9 @@ export function head(hash, render_fn) {
}
try {
- block(() => render_fn(anchor), HEAD_EFFECT);
+ // normally a branch is the child of a block and would have the EFFECT_PRESERVED flag,
+ // but since head blocks don't necessarily only have direct branch children we add it on the block itself
+ block(() => render_fn(anchor), HEAD_EFFECT | EFFECT_PRESERVED);
} finally {
if (was_hydrating) {
set_hydrating(true);
diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-title-update/_config.js b/packages/svelte/tests/runtime-runes/samples/async-derived-title-update/_config.js
new file mode 100644
index 0000000000..bda2f36efb
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-derived-title-update/_config.js
@@ -0,0 +1,12 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ async test({ assert, target }) {
+ await tick();
+
+ const p = target.querySelector('p');
+ assert.equal(p?.innerHTML, 'hello');
+ assert.equal(window.document.title, 'hello');
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-title-update/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-derived-title-update/main.svelte
new file mode 100644
index 0000000000..3af3c746f1
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-derived-title-update/main.svelte
@@ -0,0 +1,10 @@
+
+
+
{value}