can1357/oh-my-pi · error · Error
This node has no owner document
Error message
This node has no owner document
What it means
Node.documentForCreation returns the owning Document for factory calls (createElement, createTextNode, etc.). It returns `this` when the node is itself a Document, otherwise requires `ownerDocument` to have been set via setOwnerDocument; nodes created outside a document (never passed through setOwnerDocument) have no owner and throw. Internally, child-mutating operations (appendChild, insertBefore, append, prepend, textContent, replaceWith) call this to create text nodes from strings, so the error surfaces there too.
Source
Thrown at packages/utils/src/dom/core.ts:318
if (other.contains(this)) return 10;
const root = this.ownerDocument ?? this;
const nodes: Node[] = [];
const visit = (node: Node): void => {
nodes.push(node);
for (const child of node.childNodes) visit(child);
};
visit(root);
return nodes.indexOf(this) < nodes.indexOf(other) ? 4 : 2;
}
setOwnerDocument(document: Document): void {
if (this.nodeType !== NodeType.DOCUMENT) this.ownerDocument = document;
for (const child of this.childNodes) child.setOwnerDocument(document);
}
documentForCreation(): Document {
if (this instanceof Document) return this;
if (!this.ownerDocument) throw new Error("This node has no owner document");
return this.ownerDocument;
}
}
/** Text node. */
export class Text extends Node {
data: string;
serializeRaw: boolean;
constructor(data: string, ownerDocument: Document | null = null, serializeRaw = false) {
super(NodeType.TEXT, "#text", ownerDocument);
this.data = data;
this.serializeRaw = serializeRaw;
}
/** Number of UTF-16 code units. */
get length(): number {
return this.data.length;View on GitHub (pinned to 9690622007)
Solutions
- Create nodes through the document API (document.createElement / createTextNode) so ownerDocument is set automatically.
- For standalone-built nodes, call the document's adoption path (setOwnerDocument) — attaching the node to a document tree does this recursively.
- Ensure the root of your detached subtree is created by a Document so ownership propagates down to all children.
- If rehydrating nodes, re-run setOwnerDocument(document) on the root before mutating it.
Example fix
// before: node built with new, no owner document
const el = new Element("div");
el.textContent = "hi"; // throws: no owner document
// after: create via the document
const el = document.createElement("div");
el.textContent = "hi"; // ok Defensive patterns
Strategy: validation
Validate before calling
if (!node.ownerDocument && !(node instanceof Document)) {
node.setOwnerDocument(document); // adopt before mutating
}
node.textContent = "hi"; // safe: owner document now exists Type guard
function hasOwnerDocument(node: Node): boolean {
return node instanceof Document || node.ownerDocument != null;
} Try / catch
try {
node.appendChild(text);
} catch (err) {
if (err instanceof Error && err.message === "This node has no owner document") {
node.setOwnerDocument(document);
node.appendChild(text); // retry after adoption
} else {
throw err;
}
} Prevention
- Create all nodes via document.createElement/createTextNode rather than `new Element(...)`/`new Text(...)`.
- Run setOwnerDocument on the root of any standalone/rehydrated subtree before mutating it.
- Attach detached subtrees to the document before setting textContent or appending string children.
When it happens
Trigger: Appending/inserting/prepending a raw string child to a node whose ownerDocument was never assigned — i.e. a node constructed directly with `new Element(...)`/`new Text(...)` rather than via document.createElement and not attached through setOwnerDocument; calling documentForCreation() directly on such a detached node.
Common situations: Constructing DOM nodes with `new` in library/test code and mutating them before passing them through any Document; building a subtree standalone and calling textContent = '...' before adopting it; nodes deserialized/rehydrated without re-running setOwnerDocument.
Related errors
- tab.ariaSnapshot: selector ${__sel} matched no element
- Element handle selector no longer resolves
- No element matched ${spec.raw}
- tab.select() requires a <select> element
- tab.uploadFile() requires an <input type=file> element
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/45b48d21358678a7.
Report an issue: GitHub.