ianstormtaylor/slate · error · Error
Cannot get the leaf node at path [${path}] because it refers
Error message
Cannot get the leaf node at path [${path}] because it refers to a non-leaf node: ${Scrubber.stringify(
node
)} What it means
Node.leaf() returns the text node at a path, but the resolved node is an element (or the editor), not a Text node. Leaf in Slate strictly means a text node with no children, so this throws when the path points at a branch node.
Source
Thrown at packages/slate/src/interfaces/node.ts:528
while (n) {
if (Node.isText(n) || n.children.length === 0) {
break
} else {
const i = n.children.length - 1
n = n.children[i]
p.push(i)
}
}
return [n, p]
},
leaf(root: Node, path: Path): Text {
const node = Node.get(root, path)
if (!Node.isText(node)) {
throw new Error(
`Cannot get the leaf node at path [${path}] because it refers to a non-leaf node: ${Scrubber.stringify(
node
)}`
)
}
return node
},
*levels(
root: Node,
path: Path,
options: NodeLevelsOptions = {}
): Generator<NodeEntry, void, undefined> {
for (const p of Path.levels(path, options)) {
const n = Node.get(root, p)
yield [n, p]
}View on GitHub (pinned to 72a37c701e)
Solutions
- Check the node kind first: const n = Node.get(root, path); if (Text.isText(n)) ... else descend to its first text via Node.leaf(root, [...path, 0]) or Editor.leaf.
- Use Node.texts(root, { from, to }) or Editor.nodes with mode: 'lowest' to enumerate actual text paths.
- For ranges, ensure anchor/focus paths point at text nodes — Slate guarantees this only for normalized selections; re-normalize or use Range.isNormalized.
- Verify path length: a leaf path usually equals the depth of text nodes; compare against Node.texts() output for the same node.
Example fix
// before const text = Node.leaf(editor, elementPath) // throws if elementPath is an element // after const node = Node.get(editor, elementPath) const text = Text.isText(node) ? node : Node.leaf(editor, [...elementPath, 0])
Defensive patterns
Strategy: validation
Validate before calling
const node = Node.getIf(root, path)
if (!node || !Text.isText(node)) { /* resolve a real text path instead */ } Type guard
const isTextPath = (root: Node, path: Path): boolean => { const n = Node.getIf(root, path); return n !== undefined && Text.isText(n) } Prevention
- Use Node.texts / Editor.nodes mode 'lowest' to enumerate text paths.
- Check Text.isText(Node.get(...)) before calling leaf.
- Extend paths one level ([...path, 0]) when you know the node is an element.
When it happens
Trigger: Calling Node.leaf(editor, path) where path points to an element node (e.g. a paragraph); using a path from Editor.nodes() with mode: 'highest'/'lowest' incorrectly; computing a leaf path from a Range.anchor.path of an element-level selection.
Common situations: Assuming selection.anchor.path always points at text when the selection is at element level; iterating nodes and calling leaf on each path without checking node kind; off-by-one where the path stops one level too early (missing the text child index).
Related errors
- Cannot get the leaf node at path [${path}] because it refers
- Unable to find the path for Slate node: ${Scrubber.stringify
- The <text> hyperscript tag must only contain a single node's
- The <text> hyperscript tag can only contain text conten
- Cannot get the next node from the root node!
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/59221e74078b8670.
Report an issue: GitHub.