diff --git a/.changeset/nervous-kids-shake.md b/.changeset/nervous-kids-shake.md
new file mode 100644
index 000000000000..3fc642979738
--- /dev/null
+++ b/.changeset/nervous-kids-shake.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: set deriveds as `CLEAN` if they are assigned to
diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js
index cd7bbba02f91..fe27d5f4b9fa 100644
--- a/packages/svelte/src/internal/client/reactivity/deriveds.js
+++ b/packages/svelte/src/internal/client/reactivity/deriveds.js
@@ -130,7 +130,7 @@ function get_derived_parent_effect(derived) {
  * @param {Derived} derived
  * @returns {T}
  */
-function execute_derived(derived) {
+export function execute_derived(derived) {
 	var value;
 	var prev_active_effect = active_effect;
 
diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js
index e4834902fe3f..613f2cb98ebd 100644
--- a/packages/svelte/src/internal/client/reactivity/sources.js
+++ b/packages/svelte/src/internal/client/reactivity/sources.js
@@ -28,14 +28,14 @@ import {
 	UNOWNED,
 	MAYBE_DIRTY,
 	BLOCK_EFFECT,
-	ROOT_EFFECT,
-	EFFECT_IS_UPDATING
+	ROOT_EFFECT
 } from '../constants.js';
 import * as e from '../errors.js';
 import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
 import { get_stack } from '../dev/tracing.js';
 import { component_context, is_runes } from '../context.js';
 import { proxy } from '../proxy.js';
+import { execute_derived } from './deriveds.js';
 
 export let inspect_effects = new Set();
 export const old_values = new Map();
@@ -171,6 +171,14 @@ export function internal_set(source, value) {
 			}
 		}
 
+		if ((source.f & DERIVED) !== 0) {
+			// if we are assigning to a dirty derived we set it to clean/maybe dirty but we also eagerly execute it to track the dependencies
+			if ((source.f & DIRTY) !== 0) {
+				execute_derived(/** @type {Derived} */ (source));
+			}
+			set_signal_status(source, (source.f & UNOWNED) === 0 ? CLEAN : MAYBE_DIRTY);
+		}
+
 		mark_reactions(source, DIRTY);
 
 		// It's possible that the current reaction might not have up-to-date dependencies
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index a5d26412a4e6..4b913dc9b918 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -27,7 +27,7 @@ import {
 } from './constants.js';
 import { flush_tasks } from './dom/task.js';
 import { internal_set, old_values } from './reactivity/sources.js';
-import { destroy_derived_effects, update_derived } from './reactivity/deriveds.js';
+import { destroy_derived_effects, execute_derived, update_derived } from './reactivity/deriveds.js';
 import * as e from './errors.js';
 import { FILENAME } from '../../constants.js';
 import { tracing_mode_flag } from '../flags/index.js';
diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts
index 3977caae36ad..3a427e939274 100644
--- a/packages/svelte/tests/signals/test.ts
+++ b/packages/svelte/tests/signals/test.ts
@@ -1080,6 +1080,38 @@ describe('signals', () => {
 		};
 	});
 
+	test("deriveds set after they are DIRTY doesn't get updated on get", () => {
+		return () => {
+			const a = state(0);
+			const b = derived(() => $.get(a));
+
+			set(b, 1);
+			assert.equal($.get(b), 1);
+
+			set(a, 2);
+			assert.equal($.get(b), 2);
+			set(b, 3);
+
+			assert.equal($.get(b), 3);
+		};
+	});
+
+	test("unowned deriveds set after they are DIRTY doesn't get updated on get", () => {
+		return () => {
+			const a = state(0);
+			const b = derived(() => $.get(a));
+			const c = derived(() => $.get(b));
+
+			set(b, 1);
+			assert.equal($.get(c), 1);
+
+			set(a, 2);
+
+			assert.equal($.get(b), 2);
+			assert.equal($.get(c), 2);
+		};
+	});
+
 	test('deriveds containing effects work correctly when used with untrack', () => {
 		return () => {
 			let a = render_effect(() => {});