{"record":{"id":"6c9ee12dd0c3d4da","repo":"can1357/oh-my-pi","slug":"the-node-to-remove-is-not-a-child-of-this-node","errorCode":null,"errorMessage":"The node to remove is not a child of this node","messagePattern":"The node to remove is not a child of this node","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/dom/core.ts","lineNumber":237,"sourceCode":"\t\tchild.parentNode = this;\n\t\tchild.setOwnerDocument(this.documentForCreation());\n\t\tthis.childNodes.splice(index, 0, child);\n\t\treturn child;\n\t}\n\n\t/** Replace a current child with another node. */\n\treplaceChild<T extends Node>(child: Node, previous: T): T {\n\t\tconst index = this.childNodes.indexOf(previous);\n\t\tif (index < 0) throw new Error(\"The node to replace is not a child of this node\");\n\t\tthis.removeChild(previous);\n\t\tthis.insertBefore(child, this.childNodes[index] ?? null);\n\t\treturn previous;\n\t}\n\n\t/** Remove a current child. */\n\tremoveChild<T extends Node>(child: T): T {\n\t\tconst index = this.childNodes.indexOf(child);\n\t\tif (index < 0) throw new Error(\"The node to remove is not a child of this node\");\n\t\tthis.childNodes.splice(index, 1);\n\t\tchild.parentNode = null;\n\t\treturn child;\n\t}\n\n\t/** Replace all children with nodes or strings. */\n\treplaceChildren(...children: Array<Node | string>): void {\n\t\tfor (const child of this.childNodes) child.parentNode = null;\n\t\tthis.childNodes = [];\n\t\tthis.append(...children);\n\t}\n\n\t/** Append nodes or strings. */\n\tappend(...children: Array<Node | string>): void {\n\t\tfor (const child of children) {\n\t\t\tthis.appendChild(typeof child === \"string\" ? this.documentForCreation().createTextNode(child) : child);\n\t\t}\n\t}","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/dom/core.ts#L219-L255","documentation":"Node.removeChild looks up the child in `this.childNodes` and throws when it is not found (indexOf === -1). A node can only be removed from its actual current parent; calling removeChild with a node that is detached or parented elsewhere throws this error, matching the standard DOM's NotFoundError.","triggerScenarios":"Calling `parent.removeChild(child)` where `child.parentNode !== parent` — child already removed (double removal), child belongs to another parent, or child/parent arguments are inconsistent; also reached indirectly via replaceChild, which calls removeChild internally.","commonSituations":"Cleanup loops that remove the same node twice (e.g. in clear + dispose paths); removing a node from a captured parent after the node was re-parented; removing nodes during iteration over childNodes without accounting for mutation; event/dispose handlers racing each other.","solutions":["Check `child.parentNode` first and remove from `child.parentNode` (or skip if null) instead of a captured parent reference.","Guard double removals: `if (child.parentNode) child.parentNode.removeChild(child);`","If iterating while removing, iterate over a snapshot `[...parent.childNodes]` or loop by index from the end.","Wrap disposal logic so it is idempotent — mark nodes as removed or rely on parentNode nullness."],"exampleFix":"// before: removes from captured parent, may double-remove\nparent.removeChild(child); // throws if child moved or already removed\n\n// after: remove from the node's actual parent, idempotently\nchild.parentNode?.removeChild(child);","handlingStrategy":"validation","validationCode":"if (child.parentNode) {\n  child.parentNode.removeChild(child);\n}","typeGuard":"function isAttachedChild(parent: Node, child: Node): child is Node & { parentNode: Node } {\n  return parent.childNodes.includes(child);\n}","tryCatchPattern":"try {\n  parent.removeChild(child);\n} catch (err) {\n  if (err instanceof Error && err.message === \"The node to remove is not a child of this node\") {\n    // idempotent cleanup: already removed or moved — ignore\n  } else {\n    throw err;\n  }\n}","preventionTips":["Always remove via `child.parentNode?.removeChild(child)` so parent and child always agree.","Make dispose/cleanup paths idempotent — check parentNode before removing to survive double teardown.","Iterate over a snapshot (`[...parent.childNodes]`) when removing many children."],"tags":["dom","tree-structure","invalid-argument"],"backgroundTag":"dom-node-not-a-child","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}