sveltejs/svelte · error · Error

each_key_volatile

each_key_volatile

Error message

each_key_volatile
Keyed each block has key that is not idempotent — the key for item at index ${index} was `${a}` but is now `${b}`. Keys must be the same each time for a given item
https://svelte.dev/e/each_key_volatile

What it means

Runtime error `each_key_volatile`: the keyed-each key function returned a different value for the same item between renders (`a` then `b`). Keys must be idempotent — the same item must always produce the same key — otherwise the reconciler cannot track identity. The message shows the index and the two conflicting key values.

Source

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

	}
}

/**
 * Keyed each block has key that is not idempotent — the key for item at index %index% was `%a%` but is now `%b%`. Keys must be the same each time for a given item
 * @param {string} index
 * @param {string} a
 * @param {string} b
 * @returns {never}
 */
export function each_key_volatile(index, a, b) {
	if (DEV) {
		const error = new Error(`each_key_volatile\nKeyed each block has key that is not idempotent — the key for item at index ${index} was \`${a}\` but is now \`${b}\`. Keys must be the same each time for a given item\nhttps://svelte.dev/e/each_key_volatile`);

		error.name = 'Svelte error';

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

/**
 * `%rune%` cannot be used inside an effect cleanup function
 * @param {string} rune
 * @returns {never}
 */
export function effect_in_teardown(rune) {
	if (DEV) {
		const error = new Error(`effect_in_teardown\n\`${rune}\` cannot be used inside an effect cleanup function\nhttps://svelte.dev/e/effect_in_teardown`);

		error.name = 'Svelte error';

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

View on GitHub (pinned to 20b341f100)

Solutions

  1. Key on a stable, immutable property of each item (an ID assigned once at creation).
  2. If items lack a stable ID, generate and assign one when the data is first loaded (e.g. via a `crypto.randomUUID()` map) and never change it.
  3. Remove any side effects or random values from the key expression.

Example fix

{#each items as item (Math.floor(Math.random()*1000))}
<!-- key changes every render -->

{#each items as item (item.id)}
<!-- stable id assigned at load -->
Defensive patterns

Strategy: validation

Validate before calling

// Verify the key function is idempotent across two calls on the same item.
function isKeyIdempotent(items, keyFn) {
  return items.every(item => keyFn(item) === keyFn(item));
}
// also assert no side effects / no randomness in the key expression:
function riskyKeyExpr(template) {
  return /\(\s*(Math\.random|Date\.now|crypto\.)|\+\+|\-\-/.test(template);
}

Prevention

When it happens

Trigger: At runtime (DEV) when the keying function is non-deterministic or reads mutable state, e.g. `(Math.random())`, `(item.id++)`, `(Date.now())`, or a key that depends on a counter that changes each render.

Common situations: Using random/hash-of-object keys; keying on a property that the application mutates between renders; keying on an index that shifts as the list changes; objects whose `id` is assigned lazily on first access.

Related errors


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