sveltejs/svelte · error · Error

state_unsafe_mutation

state_unsafe_mutation

Error message

state_unsafe_mutation
Updating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
https://svelte.dev/e/state_unsafe_mutation

What it means

Thrown at reactivity/sources.js:162 in the set() function when writing to a $state source while active_reaction is a DERIVED, BLOCK_EFFECT (template/branch), ASYNC, or EAGER_EFFECT ($inspect) reaction, and the source is not already a tracked dependency of that reaction. Svelte forbids mutating state from inside pure reactive computations because it creates unpredictable, often cyclical, update order.

Source

Thrown at packages/svelte/src/internal/client/errors.js:492

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/state_prototype_fixed`);
	}
}

/**
 * Updating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
 * @returns {never}
 */
export function state_unsafe_mutation() {
	if (DEV) {
		const error = new Error(`state_unsafe_mutation\nUpdating state inside \`$derived(...)\`, \`$inspect(...)\` or a template expression is forbidden. If the value should not be reactive, declare it without \`$state\`\nhttps://svelte.dev/e/state_unsafe_mutation`);

		error.name = 'Svelte error';

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/state_unsafe_mutation`);
	}
}

/**
 * A `<svelte:boundary>` `reset` function cannot be called while an error is still being handled
 * @returns {never}
 */
export function svelte_boundary_reset_onerror() {
	if (DEV) {
		const error = new Error(`svelte_boundary_reset_onerror\nA \`<svelte:boundary>\` \`reset\` function cannot be called while an error is still being handled\nhttps://svelte.dev/e/svelte_boundary_reset_onerror`);

		error.name = 'Svelte error';

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`);
	}
}

View on GitHub (pinned to 20b341f100)

Solutions

  1. Move the mutation into a $effect (USER_EFFECT) rather than a $derived — effects are allowed to write state.
  2. If the value is computed, return it from the $derived instead of writing to a separate state.
  3. Wrap the write in untrack(() => {...}) only if you are certain it is safe and intentional, but prefer restructuring.

Example fix

// before
let a = $state(1);
let b = $state(0);
const sum = $derived(() => { b = a + 1; return b; }); // writes inside derived

// after
let a = $state(1);
const sum = $derived(a + 1); // pure derivation
Defensive patterns

Strategy: validation

Validate before calling

// Do not write $state inside $derived, $inspect, or template expressions.
// Move writes into $effect, or return values from $derived.
// If unavoidable, wrap the write in untrack — but prefer restructuring:
// import { untrack } from 'svelte';
// untrack(() => { stateVar = next; });

Prevention

When it happens

Trigger: Assigning to a $state variable inside the body of a $derived, inside a template expression, inside an $inspect callback, or inside a block/branch effect. The guard at sources.js:153-163 checks active_reaction flags and whether the source is in current_sources.

Common situations: Setting state inside $derived to cache a value; mutating inside a template expression like `{state.x = computed}`; writing inside $inspect; effects that should be $effect but were written as $derived; legacy store .set inside derived.

Understand the failure class

Related errors


AI-assisted analysis of sveltejs/svelte@20b341f100 (2026-08-12). Data as JSON: /api/errors/82b50dd1f0229942. Report an issue: GitHub.