{"record":{"id":"4576e31a6bfd7b0f","repo":"ianstormtaylor/slate","slug":"cannot-find-a-descendant-at-path-path-in-node","errorCode":null,"errorMessage":"Cannot find a descendant at path [${path}] in node: ${Scrubber.stringify(\n          root\n        )}","messagePattern":"Cannot find a descendant at path \\[(.+?)\\] in node: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slate/src/interfaces/node.ts","lineNumber":422,"sourceCode":"          return { ...node, text: before }\n        })\n      }\n\n      if (Path.equals(path, start.path)) {\n        modifyLeaf(newRoot, path, node => {\n          const before = node.text.slice(start.offset)\n          return { ...node, text: before }\n        })\n      }\n    }\n\n    return newRoot.children\n  },\n\n  get(root: Node, path: Path): Node {\n    const node = Node.getIf(root, path)\n    if (node === undefined) {\n      throw new Error(\n        `Cannot find a descendant at path [${path}] in node: ${Scrubber.stringify(\n          root\n        )}`\n      )\n    }\n    return node\n  },\n\n  getIf(root: Node, path: Path): Node | undefined {\n    let node = root\n\n    for (let i = 0; i < path.length; i++) {\n      const p = path[i]\n\n      if (typeof p !== 'number') {\n        throw new Error('Got non-numeric path index')\n      }\n","sourceCodeStart":404,"sourceCodeEnd":440,"githubUrl":"https://github.com/ianstormtaylor/slate/blob/72a37c701e5da4bb13a305d416d9c070d19d3a45/packages/slate/src/interfaces/node.ts#L404-L440","documentation":"Node.get() walks the tree following the numeric path, but a segment cannot be resolved — either an index is out of range, an intermediate node is a text node (which has no children), or the path is longer than the tree depth. Slate throws because a missing node cannot be represented as undefined at this API level.","triggerScenarios":"Calling Node.get(editor, [1]) when the editor has only one child; calling Node.get with a stale path after a normalization/operation changed the tree; resolving a path that descends into a text node's 'children'.","commonSituations":"Using paths captured before an async operation (selection change, normalization, collaboritive edit) and applying them after the document mutated; desynchronized document between two editor instances; incorrect manual path arithmetic when building paths.","solutions":["Re-derive paths from the current document right before use (e.g. re-read selection or re-find the node) instead of caching paths across mutations.","Check existence first with Node.has(root, path) before calling Node.get.","If operating during transforms, defer lookups until after normalization completes (e.g. after ChangeEditor.flush or outside a withNormalized call).","Validate depth: ensure the path length does not exceed tree depth via Node.ancestor or nodes() traversal."],"exampleFix":"// before\nconst node = Node.get(editor, stalePath)\n\n// after\nconst node = Node.has(editor, stalePath) ? Node.get(editor, stalePath) : fallbackNode","handlingStrategy":"validation","validationCode":"if (!Node.has(root, path)) { /* path is stale; re-derive it */ }","typeGuard":"const safeGet = (root: Node, path: Path): Node | null => Node.has(root, path) ? Node.get(root, path) : null","tryCatchPattern":"try { Node.get(root, path) } catch (e) { if (e instanceof Error && e.message.startsWith('Cannot find a descendant')) { /* re-derive path */ } throw e }","preventionTips":["Never cache paths across mutations; re-read selection or re-traverse before lookup.","Use Node.has as a pre-check whenever paths may be stale.","Recompute paths after normalization/transforms complete."],"tags":["slate","path","node-lookup","stale-state"],"backgroundTag":"slate-path-not-found","analyzedSha":"72a37c701e5da4bb13a305d416d9c070d19d3a45","analyzedAt":"2026-08-27T23:04:51.145Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}