{"record":{"id":"e46594f47d98259e","repo":"remix-run/remix","slug":"duplicate-keys-detected-in-siblings-quotedkeys","errorCode":null,"errorMessage":"Duplicate keys detected in siblings: ${quotedKeys.join(', ')}. Keys should be unique.","messagePattern":"Duplicate keys detected in siblings: (.+?)\\. Keys should be unique\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/ui/src/runtime/reconcile.ts","lineNumber":1668,"sourceCode":"  for (let node of children) {\n    if (node.key == null) continue\n\n    if (!seenKeys) {\n      seenKeys = new Set([node.key])\n      continue\n    }\n\n    if (seenKeys.has(node.key)) {\n      duplicateKeys ??= new Set()\n      duplicateKeys.add(node.key)\n    } else {\n      seenKeys.add(node.key)\n    }\n  }\n\n  if (duplicateKeys?.size) {\n    let quotedKeys = Array.from(duplicateKeys, (key) => `\"${String(key)}\"`)\n    console.warn(\n      `Duplicate keys detected in siblings: ${quotedKeys.join(', ')}. Keys should be unique.`,\n    )\n  }\n}\n\nfunction patchKeyedChildren(\n  curr: CommittedVNode[],\n  next: VNodeInput[],\n  domParent: ParentNode,\n  vParent: VNodeParent,\n  context: ReconcileContext,\n  cursor?: HydrationCursor,\n  anchor?: Node,\n): CommittedVNode[] {\n  let matches =\n    matchKeyedChildrenInOrder(curr, next) ??\n    matchKeyedChildrenAfterSingleRemoval(curr, next) ??\n    matchKeyedChildrenAfterPairSwap(curr, next)","sourceCodeStart":1650,"sourceCodeEnd":1686,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/ui/src/runtime/reconcile.ts#L1650-L1686","documentation":"During reconciliation of keyed sibling children, the UI runtime detected the same key used more than once within one parent's children. Duplicate keys make reconciliation ambiguous and can cause children to be dropped, duplicated, or mis-patched.","triggerScenarios":"Rendering an array of elements where two or more share the same key value, e.g. mapping data with non-unique ids, or mixing a hardcoded key like key=\"item\" across dynamic children.","commonSituations":"Data with duplicate ids (e.g. two records sharing an id from a bad join or seed data), index-based keys with reordering plus a static key, or string/number key collisions ('1' vs 1 both stringified).","solutions":["Ensure each sibling's key is unique within the parent, typically a stable record id","Deduplicate source data before rendering","If keys can collide legitimately, namespace them (e.g. `${type}-${id}`)"],"exampleFix":"// before\nitems.map((item) => <Row key={item.label} {...item} />)\n// after\nitems.map((item) => <Row key={item.id} {...item} />)","handlingStrategy":"validation","validationCode":"let keys = items.map((i) => i.id)\nif (new Set(keys).size !== keys.length) throw new Error('duplicate keys in input data')","typeGuard":"const hasUniqueKeys = <T>(items: T[], key: (i: T) => string | number) =>\n  new Set(items.map(key)).size === items.length","tryCatchPattern":null,"preventionTips":["Always key by stable unique record ids","Deduplicate fetched data before rendering"],"tags":["ui","reconciliation","keys","duplicate-keys"],"backgroundTag":"duplicate-react-style-keys","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}