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] = valueView on GitHub (pinned to 72a37c701e)
Solutions
- For text, use Editor.insertText/insertTextAtPoint or insert_text/remove_text operations, or Transforms.insertText.
- For children, use insert/remove/move/split node transforms instead.
- 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
- Never spread whole nodes into setNodes props.
- Use text operations for text, node transforms for children.
- Whitelist property keys instead of blacklisting when copying foreign objects.
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
- Cannot apply a "merge_node" operation at path [${path}] to n
- Cannot set properties on the root node!
- Cannot set the "then" property of a node to a function
- Cannot resolve a Slate range from a DOM event: ${event}
- Unable to find the path for Slate node: ${Scrubber.stringify
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/a95685ba3dbf363e.
Report an issue: GitHub.