ianstormtaylor/slate · error · Error
Cannot modify the editor
Error message
Cannot modify the editor
What it means
Internal utility modifyDescendant throws when asked to modify a descendant at the root path []. The editor root itself is not a descendant — modification of the root must go through the editor object, not this helper. Reaching this error usually means a transform was given an empty path where a child path was required.
Source
Thrown at packages/slate/src/utils/modify.ts:35
export const replaceChildren = <T>(
xs: T[],
index: number,
removeCount: number,
...newValues: T[]
) => [...xs.slice(0, index), ...newValues, ...xs.slice(index + removeCount)]
export const removeChildren = replaceChildren
/**
* Replace a descendant with a new node, replacing all ancestors
*/
export const modifyDescendant = <N extends Descendant>(
root: Ancestor,
path: Path,
f: (node: N) => N
) => {
if (path.length === 0) {
throw new Error('Cannot modify the editor')
}
const node = Node.get(root, path) as N
const slicedPath = path.slice()
let modifiedNode: Node = f(node)
while (slicedPath.length > 1) {
const index = slicedPath.pop()!
const ancestorNode = Node.get(root, slicedPath) as Ancestor
modifiedNode = {
...ancestorNode,
children: replaceChildren(ancestorNode.children, index, 1, modifiedNode),
}
}
const index = slicedPath.pop()!
root.children = replaceChildren(root.children, index, 1, modifiedNode)View on GitHub (pinned to 72a37c701e)
Solutions
- Ensure the path passed to node transforms points at a real descendant (length >= 1), not the root
- Debug the Path.parent/Path.previous chain that produced the empty path and handle the root case separately
- For root-level changes, use editor.children mutation or Editor-level APIs instead
Example fix
// before
const p = Path.parent(somePath) // may be []
Transforms.setNodes(editor, props, { at: p })
// after
const p = Path.parent(somePath)
if (p.length > 0) {
Transform.setNodes(editor, props, { at: p })
} else {
// handle root-level case explicitly
} Defensive patterns
Strategy: validation
Validate before calling
if (path.length === 0) {
// root: handle explicitly, never pass [] to node transforms
return
}
Transforms.setNodes(editor, props, { at: path }) Type guard
const isDescendantPath = (p: Path): boolean => Array.isArray(p) && p.length > 0
Prevention
- Handle Path.parent results that may be [] (root) separately
- Unit-test path arithmetic against minimal single-level documents
- Never forward raw computed paths into node-modifying transforms
When it happens
Trigger: Internal transforms (insertNodes, removeNodes, setNodes etc.) routed through modifyDescendant with path = []; a Path computation (Path.parent of a depth-1 path) returning [] and then used as a descendant path.
Common situations: Custom transforms computing paths with Path.parent and passing [] into node-modifying transforms; bugs in path arithmetic after deleting root-level nodes; applying ops with empty paths.
Related errors
- 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 a "split_node" operation at path [${path}] beca
- Cannot get the element at path [${path}] because it refers t
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/4dc4a95de222c600.
Report an issue: GitHub.