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
- Target a concrete element instead: use at: [0] or the current selection, or set properties directly on the editor object (editor.prop = value).
- Guard: if (path.length === 0) skip or handle specially before applying set_node.
- 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
- Never pass at: [] to Transforms.setNodes.
- Set editor-level state by direct assignment, not via operations.
- Check resolved paths after destructive transforms before setting nodes.
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
- Cannot apply a "merge_node" operation at path [${path}] beca
- Cannot get the next node from the root node!
- Cannot get the previous node from the root node!
- Cannot get the descendant node at path [${path}] because it
- Cannot apply an "insert_node" operation at path [${path}] be
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/356184294b289327.
Report an issue: GitHub.