ianstormtaylor/slate · error · Error

Cannot get the ancestor node at path [${path}] because it re

Error message

Cannot get the ancestor node at path [${path}] because it refers to a text node instead: ${Scrubber.stringify(
          node
        )}

What it means

Node.ancestor(root, path) expects a path to an element (Ancestor = Editor | Element). If the node at that path is a text node, it cannot be an ancestor, so Slate throws with a stringified copy of the offending node. Note it throws on TEXT nodes specifically; paths pointing past the tree have their own errors.

Source

Thrown at packages/slate/src/interfaces/node.ts:247

   */
  string: (node: Node) => string

  /**
   * Return a generator of all leaf text nodes in a root node.
   */
  texts: (
    root: Node,
    options?: NodeTextsOptions
  ) => Generator<NodeEntry<Text>, void, undefined>
}

// eslint-disable-next-line no-redeclare
export const Node: NodeInterface = {
  ancestor(root: Node, path: Path): Ancestor {
    const node = Node.get(root, path)

    if (Node.isText(node)) {
      throw new Error(
        `Cannot get the ancestor node at path [${path}] because it refers to a text node instead: ${Scrubber.stringify(
          node
        )}`
      )
    }

    return node
  },

  *ancestors(
    root: Node,
    path: Path,
    options: NodeAncestorsOptions = {}
  ): Generator<NodeEntry<Ancestor>, void, undefined> {
    for (const p of Path.ancestors(path, options)) {
      const n = Node.ancestor(root, p)
      const entry: NodeEntry<Ancestor> = [n, p]
      yield entry

View on GitHub (pinned to 72a37c701e)

Solutions

  1. Check the node kind first with Node.get + Node.isText (or Text.matches) before calling ancestor
  2. For point/selection paths, use Editor.parent(editor, point.path) which correctly returns the element containing the text node, rather than ancestor on the text path itself
  3. Fix path arithmetic — text nodes live at the deepest level, so their parent element is Path.parent(textPath)

Example fix

// before
const anc = Node.ancestor(editor, [0, 0]) // [0,0] is a text node -> throws

// after
const anc = Node.ancestor(editor, Path.parent([0, 0])) // the element
// or: const [[, el]] = Editor.parent(editor, [0, 0])
Defensive patterns

Strategy: type-guard

Validate before calling

const node = Node.get(editor, path)
if (!Node.isText(node)) {
  const anc = Node.ancestor(editor, path)
}

Type guard

const isAncestorPath = (root, path) =>
  !Node.isText(Node.get(root, path))

Prevention

When it happens

Trigger: Calling Node.ancestor(editor, [0, 0]) where [0,0] is a text node; Editor.parent or other APIs that delegate to ancestor receiving a text-node path; passing an odd-path (leaf-level path) computed from a Range/Point offset path.

Common situations: Off-by-one path math when navigating from a selection point path to its parent element; assuming a path refers to an element when the document nests text differently than expected.

Related errors


AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27). Data as JSON: /api/errors/fe6dad54d1f57fc0. Report an issue: GitHub.