{"record":{"id":"4dc4a95de222c600","repo":"ianstormtaylor/slate","slug":"cannot-modify-the-editor","errorCode":null,"errorMessage":"Cannot modify the editor","messagePattern":"Cannot modify the editor","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slate/src/utils/modify.ts","lineNumber":35,"sourceCode":"export const replaceChildren = <T>(\n  xs: T[],\n  index: number,\n  removeCount: number,\n  ...newValues: T[]\n) => [...xs.slice(0, index), ...newValues, ...xs.slice(index + removeCount)]\n\nexport const removeChildren = replaceChildren\n\n/**\n * Replace a descendant with a new node, replacing all ancestors\n */\nexport const modifyDescendant = <N extends Descendant>(\n  root: Ancestor,\n  path: Path,\n  f: (node: N) => N\n) => {\n  if (path.length === 0) {\n    throw new Error('Cannot modify the editor')\n  }\n\n  const node = Node.get(root, path) as N\n  const slicedPath = path.slice()\n  let modifiedNode: Node = f(node)\n\n  while (slicedPath.length > 1) {\n    const index = slicedPath.pop()!\n    const ancestorNode = Node.get(root, slicedPath) as Ancestor\n\n    modifiedNode = {\n      ...ancestorNode,\n      children: replaceChildren(ancestorNode.children, index, 1, modifiedNode),\n    }\n  }\n\n  const index = slicedPath.pop()!\n  root.children = replaceChildren(root.children, index, 1, modifiedNode)","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/ianstormtaylor/slate/blob/72a37c701e5da4bb13a305d416d9c070d19d3a45/packages/slate/src/utils/modify.ts#L17-L53","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst p = Path.parent(somePath) // may be []\nTransforms.setNodes(editor, props, { at: p })\n\n// after\nconst p = Path.parent(somePath)\nif (p.length > 0) {\n  Transform.setNodes(editor, props, { at: p })\n} else {\n  // handle root-level case explicitly\n}","handlingStrategy":"validation","validationCode":"if (path.length === 0) {\n  // root: handle explicitly, never pass [] to node transforms\n  return\n}\nTransforms.setNodes(editor, props, { at: path })","typeGuard":"const isDescendantPath = (p: Path): boolean => Array.isArray(p) && p.length > 0","tryCatchPattern":null,"preventionTips":["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"],"tags":["path","root-node","internal-utility","slate"],"backgroundTag":"invalid-path-operation","analyzedSha":"72a37c701e5da4bb13a305d416d9c070d19d3a45","analyzedAt":"2026-08-27T23:04:51.145Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}