ianstormtaylor/slate · error · Error

Cannot get child at index \`${index}\` in node: ${Scrubber.s

Error message

Cannot get child at index \`${index}\` in node: ${Scrubber.stringify(
          root
        )}

What it means

Node.child(root, index) throws when root.children[index] is undefined or null — i.e. the requested child index is out of bounds (negative or >= children.length). The message includes the offending index and a stringified copy of the root node to aid debugging.

Source

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

      yield entry
    }
  },

  child(root: Node, index: number): Descendant {
    if (Node.isText(root)) {
      throw new Error(
        `Cannot get the child of a text node: ${Scrubber.stringify(root)}`
      )
    }

    if (typeof index !== 'number') {
      throw new Error('Expected index to be a number')
    }

    const c = root.children[index] as Descendant

    if (c == null) {
      throw new Error(
        `Cannot get child at index \`${index}\` in node: ${Scrubber.stringify(
          root
        )}`
      )
    }

    return c
  },

  *children(
    root: Node,
    path: Path,
    options: NodeChildrenOptions = {}
  ): Generator<NodeEntry<Descendant>, void, undefined> {
    const { reverse = false } = options
    const ancestor = Node.ancestor(root, path)
    const { children } = ancestor
    let index = reverse ? children.length - 1 : 0

View on GitHub (pinned to 72a37c701e)

Solutions

  1. Bounds-check first: 0 <= index < (node.children?.length ?? 0)
  2. Fix loop conditions — use < children.length, not <=
  3. Re-read the node or use Node.get/Editor.nodes with paths instead of cached indices after mutations

Example fix

// before
for (let i = 0; i <= node.children.length; i++) {
  const c = Node.child(node, i) // throws on last iteration
}

// after
for (let i = 0; i < node.children.length; i++) {
  const c = Node.child(node, i)
}
Defensive patterns

Strategy: validation

Validate before calling

if (
  Number.isInteger(index) &&
  index >= 0 &&
  index < node.children.length
) {
  const c = Node.child(node, index)
}

Type guard

const isIndexInBounds = (node, i) =>
  Number.isInteger(i) && i >= 0 && i < node.children.length

Prevention

When it happens

Trigger: Calling Node.child(node, node.children.length) (classic off-by-one when iterating <= instead of <); using a stale index after children were removed; negative indices; assuming an element has children when it is empty.

Common situations: Loop bounds mistakes in manual traversal; cached paths/indices invalidated by concurrent edits; empty elements (children: []) accessed with index 0.

Related errors


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