ianstormtaylor/slate · error · Error
Cannot resolve a Slate node from DOM node: ${domEl}
Error message
Cannot resolve a Slate node from DOM node: ${domEl} What it means
Thrown by DOMEditor.toSlateNode when a DOM element cannot be mapped back to a Slate node — the element is not inside the editor's managed DOM (no data-slate-node ancestor with a known mapping).
Source
Thrown at packages/slate-dom/src/plugin/dom-editor.ts:688
) as HTMLElement
const isEndAtZeroWidth = !!endEl.getAttribute('data-slate-zero-width')
domRange.setStart(startNode, isStartAtZeroWidth ? 1 : startOffset)
domRange.setEnd(endNode, isEndAtZeroWidth ? 1 : endOffset)
return domRange
},
toSlateNode: (editor, domNode) => {
let domEl = isDOMElement(domNode) ? domNode : domNode.parentElement
if (domEl && !domEl.hasAttribute('data-slate-node')) {
domEl = domEl.closest(`[data-slate-node]`)
}
const node = domEl ? ELEMENT_TO_NODE.get(domEl as HTMLElement) : null
if (!node) {
throw new Error(`Cannot resolve a Slate node from DOM node: ${domEl}`)
}
return node
},
toSlatePoint: <T extends boolean>(
editor: DOMEditor,
domPoint: DOMPoint,
options: {
exactMatch: boolean
suppressThrow: T
searchDirection?: 'forward' | 'backward'
}
): T extends true ? Point | null : Point => {
const { exactMatch, suppressThrow } = options
const [nearestNode, nearestOffset] = exactMatch
? domPoint
: normalizeDOMPoint(domPoint)View on GitHub (pinned to 72a37c701e)
Solutions
- Check DOMEditor.hasDOMNode(editor, el) before calling toSlateNode
- Use event.target.closest('[data-slate-node]') to ensure you start from a Slate-managed element
- For void element UI, use the element's data attributes or the void node context rather than toSlateNode on portals
- Verify you're using the correct editor instance
Example fix
// before
const node = DOMEditor.toSlateNode(editor, toolbarEl)
// after
if (DOMEditor.hasDOMNode(editor, toolbarEl)) {
const node = DOMEditor.toSlateNode(editor, toolbarEl)
} Defensive patterns
Strategy: type-guard
Validate before calling
const el = (event.target as HTMLElement).closest('[data-slate-node]')
if (el && DOMEditor.hasDOMNode(editor, el)) {
const node = DOMEditor.toSlateNode(editor, el)
} Type guard
const isSlateManagedEl = (editor: Editor, el: HTMLElement): boolean => DOMEditor.hasDOMNode(editor, el)
Try / catch
try { DOMEditor.toSlateNode(editor, el) } catch (e) { if (/Cannot resolve a Slate node/.test(e.message)) ignore non-Slate DOM; else throw e } Prevention
- Always closest('[data-slate-node]') from event targets
- Guard with hasDOMNode before toSlateNode
- Don't feed portal/toolbar elements to editor APIs
When it happens
Trigger: Passing an element from outside the Slate editable (toolbars, portals, other editors), or an element inside the editor whose WeakMap entry was cleared after unmount/re-render.
Common situations: Event handlers on custom void elements or menus passing their own container element to toSlateNode; multiple editors where the element belongs to the other instance; inspecting DOM after the editor remounted.
Related errors
- Cannot resolve a Slate range from a DOM event: ${event}
- Cannot resolve a DOM node from Slate node: ${Scrubber.string
- Expected index to be a number
- Unable to find the path for Slate node: ${Scrubber.stringify
- Could not set focus, editor seems stuck with pending operati
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/e2b3d10321509eb4.
Report an issue: GitHub.