sveltejs/svelte · error · Error

each_key_duplicate

each_key_duplicate

Error message

each_key_duplicate
${value ? `Keyed each block has duplicate key `${value}` at indexes ${a} and ${b}` : `Keyed each block has duplicate key at indexes ${a} and ${b}`}
https://svelte.dev/e/each_key_duplicate

What it means

Runtime error `each_key_duplicate`: a keyed `{#each items as item (key)}` block produced the same key value for two different items at the same indexes `a` and `b`. Svelte keys must be unique per item so the diff/patch logic can track elements. The key value is included when available, omitted otherwise.

Source

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

/**
 * Keyed each block has duplicate key `%value%` at indexes %a% and %b%
 * @param {string} a
 * @param {string} b
 * @param {string | undefined | null} [value]
 * @returns {never}
 */
export function each_key_duplicate(a, b, value) {
	if (DEV) {
		const error = new Error(`each_key_duplicate\n${value
			? `Keyed each block has duplicate key \`${value}\` at indexes ${a} and ${b}`
			: `Keyed each block has duplicate key at indexes ${a} and ${b}`}\nhttps://svelte.dev/e/each_key_duplicate`);

		error.name = 'Svelte error';

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

/**
 * 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 {

View on GitHub (pinned to 20b341f100)

Solutions

  1. Use a truly unique key — typically the item's primary key (`(item.id)`).
  2. If the data has no unique field, derive one (e.g. compose `(item.type + '-' + item.id)`) or sanitize duplicates upstream.
  3. Avoid `(index)` as the key when the list can be reordered, inserted into, or filtered.

Example fix

{#each items as item (item.status)} <!-- duplicate statuses -->

{#each items as item (item.id)} <!-- unique -->
Defensive patterns

Strategy: validation

Validate before calling

// Detect non-unique keys in a list before render (data-side check).
function findDuplicateKeys(items, keyFn) {
  const seen = new Map();
  const dups = [];
  for (let i = 0; i < items.length; i++) {
    const k = keyFn(items[i]);
    if (seen.has(k)) dups.push({ key: k, a: seen.get(k), b: i });
    else seen.set(k, i);
  }
  return dups;
}

Prevention

When it happens

Trigger: At runtime (DEV) when the keyed-each reconciler detects that two items in the same list yield identical keys. Common with `(item.id)` when IDs collide, or with `(index)`-style keys when items reorder.

Common situations: Backend returning duplicate IDs in a list; using a non-unique field (e.g. `(item.status)`) as the key; merging two lists that share keys; using array index as key while inserting/removing items.

Related errors


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