ianstormtaylor/slate · error · Error

Cannot set properties on the root node!

Error message

Cannot set properties on the root node!

What it means

A set_node operation sets properties on a node. The root node is the top-level Editor object, not a regular Node, so Slate throws when set_node is applied with path [].

Source

Thrown at packages/slate/src/interfaces/transforms/general.ts:248

        modifyLeaf(editor, path, node => {
          const before = node.text.slice(0, offset)
          const after = node.text.slice(offset + text.length)

          return {
            ...node,
            text: before + after,
          }
        })

        transformSelection = true
        break
      }

      case 'set_node': {
        const { path, properties, newProperties } = op

        if (path.length === 0) {
          throw new Error(`Cannot set properties on the root node!`)
        }

        modifyDescendant(editor, path, node => {
          const newNode = { ...node }

          for (const key in newProperties) {
            if (NON_SETTABLE_NODE_PROPERTIES.includes(key)) {
              throw new Error(`Cannot set the "${key}" property of nodes!`)
            }

            const value = newProperties[<keyof Node>key]

            // Make sure we're not setting `then` to a function, since this will
            // cause the node to be treated as a Promise-like object, which can
            // cause unexpected behaviour when returning the node from async
            // functions.
            if (key === 'then' && typeof value === 'function') {
              throw new Error(

View on GitHub (pinned to 72a37c701e)

Solutions

  1. Target a concrete element instead: use at: [0] or the current selection, or set properties directly on the editor object (editor.prop = value).
  2. Guard: if (path.length === 0) skip or handle specially before applying set_node.
  3. If using Editor.withNormalization custom code, make sure paths passed to setNodes never degrade to [].

Example fix

// before
Transforms.setNodes(editor, { align: 'center' }, { at: [] })

// after
Transforms.setNodes(editor, { align: 'center' }, { at: [0] })
// or set a root-level (editor) property directly:
// editor.someProp = value
Defensive patterns

Strategy: validation

Validate before calling

if (path.length > 0) {
  Transforms.setNodes(editor, props, { at: path })
} else {
  Object.assign(editor, props) // root-level properties set directly
}

Type guard

function isDescendantPath(path: Path): boolean {
  return path.length > 0
}

Prevention

When it happens

Trigger: Applying { type: 'set_node', path: [], ... } or calling Transforms.setNodes(editor, props, { at: [] }); also when a computed path collapses to [] after transforms.

Common situations: Calling Transforms.setNodes with at pointing at the whole editor instead of a specific element; selections/paths resolving to the root after deletions; custom normalizers setting properties on editor by path.

Related errors


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