{"record":{"id":"75c2e858aa0cfac7","repo":"HelloZeroNet/ZeroNet","slug":"parentvnode-vnodeselector-had-a-childnode-vno-75c2e8","errorCode":null,"errorMessage":"${parentVNode.vnodeSelector} had a ${childNode.vnodeSelector} child added, but there is now more than one. You must add unique key properties to make them distinguishable.","messagePattern":"(.+?) had a (.+?) child added, but there is now more than one\\. You must add unique key properties to make them distinguishable\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/UiConfig/media/js/lib/maquette.js","lineNumber":323,"sourceCode":"        }\n        if (domNode.parentNode) {\n            domNode.parentNode.removeChild(domNode);\n        }\n    };\n    var checkDistinguishable = function (childNodes, indexToCheck, parentVNode, operation) {\n        var childNode = childNodes[indexToCheck];\n        if (childNode.vnodeSelector === '') {\n            return;    // Text nodes need not be distinguishable\n        }\n        var properties = childNode.properties;\n        var key = properties ? properties.key === undefined ? properties.bind : properties.key : undefined;\n        if (!key) {\n            for (var i = 0; i < childNodes.length; i++) {\n                if (i !== indexToCheck) {\n                    var node = childNodes[i];\n                    if (same(node, childNode)) {\n                        if (operation === 'added') {\n                            throw new Error(parentVNode.vnodeSelector + ' had a ' + childNode.vnodeSelector + ' child ' + 'added, but there is now more than one. You must add unique key properties to make them distinguishable.');\n                        } else {\n                            throw new Error(parentVNode.vnodeSelector + ' had a ' + childNode.vnodeSelector + ' child ' + 'removed, but there were more than one. You must add unique key properties to make them distinguishable.');\n                        }\n                    }\n                }\n            }\n        }\n    };\n    var createDom;\n    var updateDom;\n    var updateChildren = function (vnode, domNode, oldChildren, newChildren, projectionOptions) {\n        if (oldChildren === newChildren) {\n            return false;\n        }\n        oldChildren = oldChildren || emptyArray;\n        newChildren = newChildren || emptyArray;\n        var oldChildrenLength = oldChildren.length;\n        var newChildrenLength = newChildren.length;","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/plugins/UiConfig/media/js/lib/maquette.js#L305-L341","documentation":"checkDistinguishable runs when a child is added during a re-render; if the new child is indistinguishable from another existing child of the same parent (no unique key), maquette cannot know which node to update and throws. Keys give each sibling a stable identity for the diff.","triggerScenarios":"Calling projection.update with a new vnode tree that adds a child identical (same selector, text, no key) to an existing sibling of the same parent, e.g. adding a second h('li', ['item']) to a list.","commonSituations":"Dynamically appending repeated list items (tasks, rows, comments) without keys; rendering placeholder items that are all identical.","solutions":["Add a unique `key` property to each repeated child: h('li', { key: item.id }, ...).","If no natural id exists, add a counter-based unique key when items are created.","Include distinguishing content (e.g. index) so siblings differ, though keys are the proper fix."],"exampleFix":"// before\nitems.map(i => h('li', [i.name]))\n// after\nitems.map(i => h('li', { key: i.id }, [i.name]))","handlingStrategy":"validation","validationCode":"function childrenHaveKeys(vnode) {\n  return (vnode.children || []).every(function (c) { return c == null || c.properties == null || c.properties.key != null || !isRepeatedSibling(c, vnode.children); });\n}\n","typeGuard":"function allListItemsKeyed(items) {\n  return items.every(function (i) { return i.properties && typeof i.properties.key !== 'undefined'; });\n}","tryCatchPattern":"try {\n  projection.update(newTree);\n} catch (e) {\n  if (/You must add unique key properties/.test(e.message)) { console.error('Add key properties to repeated children:', e.message); }\n  throw e;\n}","preventionTips":["Always add key: item.id to children rendered from collections.","Generate unique keys at item creation time (counter or uuid).","Never rely on item text or selector to distinguish siblings."],"tags":["virtual-dom","keys","list-rendering"],"backgroundTag":"missing-key-prop","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}