diff --git a/.changeset/silly-walls-fail.md b/.changeset/silly-walls-fail.md
new file mode 100644
index 0000000000..6f364e7f8a
--- /dev/null
+++ b/.changeset/silly-walls-fail.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: coerce nullish `
` to empty string
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js
index e6f4202a01..98d7880b25 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js
@@ -12,8 +12,19 @@ export function TitleElement(node, context) {
/** @type {any} */ (node.fragment.nodes),
context
);
+ const evaluated = context.state.scope.evaluate(value);
- const statement = b.stmt(b.assignment('=', b.id('$.document.title'), value));
+ const statement = b.stmt(
+ b.assignment(
+ '=',
+ b.id('$.document.title'),
+ evaluated.is_known
+ ? b.literal(evaluated.value)
+ : evaluated.is_defined
+ ? value
+ : b.logical('??', value, b.literal(''))
+ )
+ );
if (has_state) {
context.state.update.push(statement);
diff --git a/packages/svelte/tests/runtime-runes/samples/title-nullish/_config.js b/packages/svelte/tests/runtime-runes/samples/title-nullish/_config.js
new file mode 100644
index 0000000000..819d6b620e
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/title-nullish/_config.js
@@ -0,0 +1,7 @@
+import { test } from '../../test';
+
+export default test({
+ test({ assert, target }) {
+ assert.equal(target.ownerDocument.title, '');
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/title-nullish/main.svelte b/packages/svelte/tests/runtime-runes/samples/title-nullish/main.svelte
new file mode 100644
index 0000000000..f1fa7e7b84
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/title-nullish/main.svelte
@@ -0,0 +1,6 @@
+
+
+ {thing.thing}
+
\ No newline at end of file