Repository: sveltejs/svelte (JavaScript)

Issue:
Svelte 5: stores cause $effect run twice on initial load
### Describe the bug

Title pretty much says all. reading store value in `$effect` causes `$effect` run twice on inital load of component.

### Reproduction

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAACl1QbWuEMAz-KyEIpyhzn50Kx37G3AevF0e5mkqbbgzxv4_aY-72oSl5XvKErDhpQx6btxV5nAkbPC8LVijfS2z8JxkhrNDb4FREWq-cXqQfeBA9L9YJrBBY3KhusMHk7AynZDu9PIi-nJbxYuifqvZiXdLyIMqyF9ihVxtYoPv15c9FVBgSUHcq8zJKJPak-DKaJlKS5wV0Paw7LNkxLwH3fR9VMTywlOXRsreGnoz9yHeqSMy2_7G29XENbi9BxDJYbpTR6tatafyf9LLces3K0UwsbZ0MPVY426ueNF2xERdoe99-AF9SIOmZAQAA

### Logs

_No response_

### System Info

```shell
System:
  OS: Linux 5.15 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
  CPU: (20) x64 13th Gen Intel(R) Core(TM) i5-13600KF
  Memory: 27.96 GB / 31.25 GB
  Container: Yes
  Shell: 5.1.16 - /bin/bash
Binaries:
  Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node
  npm: 10.4.0 - ~/.nvm/versions/node/v20.11.1/bin/npm
  pnpm: 8.15.3 - ~/.nvm/versions/node/v20.11.1/bin/pnpm
  bun: 1.0.0 - ~/.bun/bin/bun
npmPackages:
  svelte: ^5.0.0-next.56 => 5.0.0-next.56
```


### Severity

annoyance


Discussion:
Not sure if this helps to debug this issue but adding `{$storeCount}` to html changes its behavior and makes it run only once.



Patch:
diff --git a/.changeset/cool-roses-trade.md b/.changeset/cool-roses-trade.md
new file mode 100644
index 000000000000..ae05a8f8b416
--- /dev/null
+++ b/.changeset/cool-roses-trade.md
@@ -0,0 +1,5 @@
+---
+"svelte": patch
+---
+
+fix: improve effect over-fire on store subscription init
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index dbcffed933bd..8db5cfa54f91 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -1210,8 +1210,11 @@ export function set_signal_value(signal, value) {
 		//
 		// $effect(() => x++)
 		//
+		// We additionally want to skip this logic for when ignore_mutation_validation is
+		// true, as stores write to source signal on initialization.
 		if (
 			is_runes(null) &&
+			!ignore_mutation_validation &&
 			current_effect !== null &&
 			current_effect.c === null &&
 			(current_effect.f & CLEAN) !== 0


Test patch:
diff --git a/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/_config.js b/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/_config.js
new file mode 100644
index 000000000000..13ada4492567
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/_config.js
@@ -0,0 +1,22 @@
+import { test } from '../../test';
+import { log } from './log.js';
+
+export default test({
+	html: `<button>increment</button>`,
+
+	before_test() {
+		log.length = 0;
+	},
+
+	async test({ assert, target }) {
+		const btn = target.querySelector('button');
+
+		assert.deepEqual(log, [1]);
+
+		await btn?.click();
+		assert.deepEqual(log, [1, 2]);
+
+		await btn?.click();
+		assert.deepEqual(log, [1, 2, 3]);
+	}
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/log.js b/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/log.js
new file mode 100644
index 000000000000..d3df521f4da7
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/log.js
@@ -0,0 +1,2 @@
+/** @type {any[]} */
+export const log = [];
diff --git a/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/main.svelte b/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/main.svelte
new file mode 100644
index 000000000000..27c07d779c65
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/main.svelte
@@ -0,0 +1,18 @@
+<script>
+	import { untrack } from 'svelte';
+	import { writable } from 'svelte/store';
+	import { log } from './log';
+
+	const storeCount = writable(0)
+	let count = $state(0);
+
+	$effect(() => {
+		$storeCount;
+		untrack(() => {
+			count++;
+			log.push(count);
+		});
+	});
+</script>
+
+<button on:click={() => $storeCount++}>increment</button>