ianstormtaylor/slate · error · Error
Cannot resolve a Slate range from DOM range: ${domRange}
Error message
Cannot resolve a Slate range from DOM range: ${domRange} What it means
Thrown by DOMEditor.toSlateRange when the native DOM range's anchor/focus nodes or offsets are null/undefined, so no Slate range can be derived. Usually means the selection object was empty or collapsed to nothing at read time.
Source
Thrown at packages/slate-dom/src/plugin/dom-editor.ts:1066
} else {
isCollapsed = domRange.isCollapsed
}
} else {
anchorNode = domRange.startContainer
anchorOffset = domRange.startOffset
focusNode = domRange.endContainer
focusOffset = domRange.endOffset
isCollapsed = domRange.collapsed
}
}
if (
anchorNode == null ||
focusNode == null ||
anchorOffset == null ||
focusOffset == null
) {
throw new Error(
`Cannot resolve a Slate range from DOM range: ${domRange}`
)
}
// COMPAT: Firefox sometimes includes an extra \n (rendered by TextString
// when isTrailing is true) in the focusOffset, resulting in an invalid
// Slate point. (2023/11/01)
if (
IS_FIREFOX &&
focusNode.textContent?.endsWith('\n\n') &&
focusOffset === focusNode.textContent.length
) {
focusOffset--
}
const anchor = DOMEditor.toSlatePoint(editor, [anchorNode, anchorOffset], {
exactMatch,
suppressThrow,View on GitHub (pinned to 72a37c701e)
Solutions
- Check selection.rangeCount > 0 and that the editable contains the selection before converting
- Defer the read with requestAnimationFrame when handling selectionchange races
- Use DOMEditor.toSlateRange(editor, domRange, { suppressThrow: true }) and handle null
- Ensure focus is inside the editable before reading the native selection
Example fix
// before
const sel = window.getSelection()
const range = DOMEditor.toSlateRange(editor, sel.getRangeAt(0))
// after
const sel = window.getSelection()
if (sel && sel.rangeCount > 0) {
const range = DOMEditor.toSlateRange(editor, sel.getRangeAt(0), { suppressThrow: true })
} Defensive patterns
Strategy: validation
Validate before calling
const sel = window.getSelection()
if (sel && sel.rangeCount > 0 && DOMEditor.hasDOMNode(editor, sel.anchorNode)) {
const range = DOMEditor.toSlateRange(editor, sel.getRangeAt(0), { suppressThrow: true })
} Type guard
const hasNativeSelection = (sel: Selection | null): sel is Selection => !!sel && sel.rangeCount > 0 && sel.anchorNode != null && sel.focusNode != null
Try / catch
try { DOMEditor.toSlateRange(editor, domRange) } catch (e) { if (/Cannot resolve a Slate range/.test(e.message)) return null; else throw e } Prevention
- Check rangeCount and editable containment before converting selection
- Defer selection reads past selectionchange races (rAF)
- Use suppressThrow for user-driven selection inspection
When it happens
Trigger: Reading window.getSelection() when it contains no ranges (e.g. right after blur, or before the browser updates selection), or converting a DOMRange whose containers were detached from the document.
Common situations: onSelect/selectionchange handlers racing browser selection updates; reading selection after the editable was blurred or unmounted; Firefox-specific extra-newline offset issues preceding this guard.
Related errors
- Cannot resolve a Slate range from a DOM event: ${event}
- Cannot resolve a DOM point from Slate point: ${Scrubber.stri
- Cannot resolve a Slate point from DOM point: ${domPoint}
- The <selection> hyperscript tag must have an <anchor> tag as
- The <selection> hyperscript tag must have a <focus> tag as a
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/2bd1d66e752061d2.
Report an issue: GitHub.