remix-run/remix · warning
Duplicate keys detected in siblings: ${quotedKeys.join(', ')
Error message
Duplicate keys detected in siblings: ${quotedKeys.join(', ')}. Keys should be unique. What it means
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.
Source
Thrown at packages/ui/src/runtime/reconcile.ts:1668
for (let node of children) {
if (node.key == null) continue
if (!seenKeys) {
seenKeys = new Set([node.key])
continue
}
if (seenKeys.has(node.key)) {
duplicateKeys ??= new Set()
duplicateKeys.add(node.key)
} else {
seenKeys.add(node.key)
}
}
if (duplicateKeys?.size) {
let quotedKeys = Array.from(duplicateKeys, (key) => `"${String(key)}"`)
console.warn(
`Duplicate keys detected in siblings: ${quotedKeys.join(', ')}. Keys should be unique.`,
)
}
}
function patchKeyedChildren(
curr: CommittedVNode[],
next: VNodeInput[],
domParent: ParentNode,
vParent: VNodeParent,
context: ReconcileContext,
cursor?: HydrationCursor,
anchor?: Node,
): CommittedVNode[] {
let matches =
matchKeyedChildrenInOrder(curr, next) ??
matchKeyedChildrenAfterSingleRemoval(curr, next) ??
matchKeyedChildrenAfterPairSwap(curr, next)View on GitHub (pinned to 9696913134)
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}`)
Example fix
// before
items.map((item) => <Row key={item.label} {...item} />)
// after
items.map((item) => <Row key={item.id} {...item} />) Defensive patterns
Strategy: validation
Validate before calling
let keys = items.map((i) => i.id)
if (new Set(keys).size !== keys.length) throw new Error('duplicate keys in input data') Type guard
const hasUniqueKeys = <T>(items: T[], key: (i: T) => string | number) => new Set(items.map(key)).size === items.length
Prevention
- Always key by stable unique record ids
- Deduplicate fetched data before rendering
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- popover.surface() requires a registered anchor before openin
- render called after component was removed, potential applica
- ${cascadingComponentUpdateCount} cascading component updates
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/e46594f47d98259e.
Report an issue: GitHub.