{"record":{"id":"71ba271a0f8e02c9","repo":"ianstormtaylor/slate","slug":"unable-to-find-the-path-for-slate-node-scrubber","errorCode":null,"errorMessage":"Unable to find the path for Slate node: ${Scrubber.stringify(node)}","messagePattern":"Unable to find the path for Slate node: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slate-dom/src/plugin/dom-editor.ts","lineNumber":415,"sourceCode":"      if (parent == null) {\n        if (child === editor) {\n          return path\n        } else {\n          break\n        }\n      }\n\n      const i = NODE_TO_INDEX.get(child)\n\n      if (i == null) {\n        break\n      }\n\n      path.unshift(i)\n      child = parent\n    }\n\n    throw new Error(\n      `Unable to find the path for Slate node: ${Scrubber.stringify(node)}`\n    )\n  },\n\n  focus: (editor, options = { retries: 5 }) => {\n    // Return if already focused\n    if (IS_FOCUSED.get(editor)) {\n      return\n    }\n\n    // Return if no dom node is associated with the editor, which means the editor is not yet mounted\n    // or has been unmounted. This can happen especially, while retrying to focus the editor.\n    if (!EDITOR_TO_ELEMENT.get(editor)) {\n      return\n    }\n\n    // Retry setting focus if the editor has pending operations.\n    // The DOM (selection) is unstable while changes are applied.","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/ianstormtaylor/slate/blob/72a37c701e5da4bb13a305d416d9c070d19d3a45/packages/slate-dom/src/plugin/dom-editor.ts#L397-L433","documentation":"Thrown by DOMEditor.findPath when walking up from a Slate node to the root via parent links fails to reach the root editor. This means the node is not attached to this editor's tree (detached, from another editor, or a stale reference after normalization).","triggerScenarios":"Calling toSlateNode/findPath with a DOM element whose mapped Slate node was removed by normalization, or calling editor.findPath on a node object captured before a normalize/apply pass removed it.","commonSituations":"Keeping stale node references across edits (normalization replaces nodes), rendering one editor's node in another editor, or reading paths during an asynchronous callback after the document changed.","solutions":["Re-resolve the node from the DOM right before finding its path","Do not cache Slate node objects across editing operations; store paths or keys instead","Perform the lookup synchronously within the same change cycle","Verify the node belongs to this editor with Node.has(editor, path) or key comparison"],"exampleFix":"// before\nconst savedNode = DOMEditor.toSlateNode(editor, el)\n// ... later after edits\nconst path = DOMEditor.findPath(editor, savedNode)\n// after\nconst node = DOMEditor.toSlateNode(editor, el) // fresh\nconst path = DOMEditor.findPath(editor, node)","handlingStrategy":"validation","validationCode":"const node = DOMEditor.toSlateNode(editor, domEl)\nconst path = DOMEditor.findPath(editor, node) // only safe synchronously\n// validate a cached node still belongs:\ntry { Node.get(editor, DOMEditor.findPath(editor, node)) } catch { /* stale */ }","typeGuard":"null","tryCatchPattern":"try { path = DOMEditor.findPath(editor, node) } catch (e) { if (/Unable to find the path/.test(e.message)) re-resolve node from DOM; else throw e }","preventionTips":["Never cache Slate node objects across edits; store keys or paths","Re-resolve nodes from DOM right before use","Keep DOM lookups within the same render/change cycle"],"tags":["slate","path","normalization","stale-reference"],"backgroundTag":"stale-node-reference","analyzedSha":"72a37c701e5da4bb13a305d416d9c070d19d3a45","analyzedAt":"2026-08-27T23:04:51.145Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}