ianstormtaylor/slate · error · Error

Cannot set the "${key}" property of nodes!

Error message

Cannot set the "${key}" property of nodes!

What it means

set_node refuses to set properties listed in NON_SETTABLE_NODE_PROPERTIES (id, text, children) because changing them via set_node would corrupt the document structure; those changes have dedicated operations (insert_text, split_node, etc.).

Source

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

        })

        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(
                'Cannot set the "then" property of a node to a function'
              )
            }

            if (value == null) {
              delete newNode[<keyof Node>key]
            } else {
              newNode[<keyof Node>key] = value

View on GitHub (pinned to 72a37c701e)

Solutions

  1. For text, use Editor.insertText/insertTextAtPoint or insert_text/remove_text operations, or Transforms.insertText.
  2. For children, use insert/remove/move/split node transforms instead.
  3. For id (or custom non-structural props incorrectly grouped), check NON_SETTABLE_NODE_PROPERTIES and mutate the node directly if it's truly a custom property not in that list.

Example fix

// before
Transforms.setNodes(editor, { text: 'new text' }, { at: path })

// after
Transforms.insertText(editor, 'new text', { at: path })
// for ids, mutate directly:
// Node.get(editor, path).id = newId (inside withChanges)
Defensive patterns

Strategy: validation

Validate before calling

const NON_SETTABLE = ['id', 'text', 'children']
const safe = Object.fromEntries(
  Object.entries(props).filter(([k]) => !NON_SETTABLE.includes(k))
)
Transforms.setNodes(editor, safe, { at: path })

Type guard

function isSettableProp(key: string): boolean {
  return !['id', 'text', 'children'].includes(key)
}

Prevention

When it happens

Trigger: Applying set_node whose newProperties contains 'id', 'text', or 'children' — e.g. Transforms.setNodes(editor, { text: 'hi' }) or trying to change a node's id via setNodes.

Common situations: Trying to update node ids during a migration with setNodes instead of direct mutation; attempting text edits through setNodes; copy-pasted code that spreads a whole node into setNodes' props.

Related errors


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