can1357/oh-my-pi · error · Error

The reference node is not a child of this node

Error message

The reference node is not a child of this node

What it means

Node.insertBefore requires the `reference` node to be a direct child of the node it is called on; it locates reference via `this.childNodes.indexOf(reference)` and throws when the index is -1. Passing null is allowed and delegates to appendChild. Like the standard DOM, this guards against inserting relative to a node that isn't actually a sibling-position marker on this parent.

Source

Thrown at packages/utils/src/dom/core.ts:213

	appendChild<T extends Node>(child: T): T {
		const node: Node = child;
		if (node === this || node.contains(this)) throw new Error("The new child is an ancestor of this node");
		if (child instanceof DocumentFragment) {
			for (const nested of [...child.childNodes]) this.appendChild(nested);
			return child;
		}
		child.parentNode?.removeChild(child);
		child.parentNode = this;
		child.setOwnerDocument(this.documentForCreation());
		this.childNodes.push(child);
		return child;
	}

	/** Insert a node before a current child, or append for null. */
	insertBefore<T extends Node>(child: T, reference: Node | null): T {
		if (reference === null) return this.appendChild(child);
		const index = this.childNodes.indexOf(reference);
		if (index < 0) throw new Error("The reference node is not a child of this node");
		if (child instanceof DocumentFragment) {
			for (const nested of [...child.childNodes]) this.insertBefore(nested, reference);
			return child;
		}
		child.parentNode?.removeChild(child);
		child.parentNode = this;
		child.setOwnerDocument(this.documentForCreation());
		this.childNodes.splice(index, 0, child);
		return child;
	}

	/** Replace a current child with another node. */
	replaceChild<T extends Node>(child: Node, previous: T): T {
		const index = this.childNodes.indexOf(previous);
		if (index < 0) throw new Error("The node to replace is not a child of this node");
		this.removeChild(previous);
		this.insertBefore(child, this.childNodes[index] ?? null);
		return previous;

View on GitHub (pinned to 9690622007)

Solutions

  1. Assert `ref.parentNode === parent` before calling insertBefore; if false, you have the wrong parent or a stale reference.
  2. If the reference node may have been removed, re-look it up (or use appendChild when no position marker is needed).
  3. Pass `null` as reference when you simply want to append at the end.
  4. When moving nodes between parents, insert into the node's actual `parentNode` rather than a captured parent variable.

Example fix

// before: ref belongs to another parent
otherParent.insertBefore(newChild, marker); // throws: marker is not otherParent's child

// after: use the marker's actual parent, or null to append
(marker.parentNode ?? parent).insertBefore(newChild, marker.parentNode === parent ? marker : null);
Defensive patterns

Strategy: type-guard

Type guard

function isDirectChild(parent: Node, node: Node): node is Node & { parentNode: Node } {
  return parent.childNodes.includes(node);
}
// call before: if (isDirectChild(parent, ref)) parent.insertBefore(child, ref); else parent.appendChild(child);

Try / catch

try {
  parent.insertBefore(child, ref);
} catch (err) {
  if (err instanceof Error && err.message === "The reference node is not a child of this node") {
    parent.appendChild(child); // fallback: append at end
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling `parent.insertBefore(child, ref)` where `ref` is not currently a direct child of `parent` — e.g. ref was already removed, belongs to a different parent, or parent/ref were swapped; also via replaceChild (which uses insertBefore internally) and prepend wrappers.

Common situations: Holding a stale reference after the reference node was removed or moved elsewhere; inserting into a different parent than owns the marker node; passing an element from a detached copy while the live tree's counterpart is expected; iteration that removes nodes while using one as the insertion point.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/0421b5e7910ba4d7. Report an issue: GitHub.