ianstormtaylor/slate · error · Error
Slate hyperscript ranges must have both `<anchor />` and `<f
Error message
Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<focus />`. For collapsed selections, use `<cursor />` instead.
What it means
Thrown by hyperscript's createEditor when a <focus /> token exists in the value but no <anchor /> token does. The range pair is incomplete, so a Slate selection cannot be constructed.
Source
Thrown at packages/slate-hyperscript/src/creators.ts:283
}
}
for (const { ref, offset } of getPoints(node)) {
if (ref) {
ref.offset = offset
ref.path = path
}
}
}
if (selection.anchor && !selection.focus) {
throw new Error(
`Slate hyperscript ranges must have both \`<anchor />\` and \`<focus />\` defined if one is defined, but you only defined \`<anchor />\`. For collapsed selections, use \`<cursor />\` instead.`
)
}
if (!selection.anchor && selection.focus) {
throw new Error(
`Slate hyperscript ranges must have both \`<anchor />\` and \`<focus />\` defined if one is defined, but you only defined \`<focus />\`. For collapsed selections, use \`<cursor />\` instead.`
)
}
if (selectionChild != null) {
editor.selection = selectionChild
} else if (Range.isRange(selection)) {
editor.selection = selection
}
return editor
}
View on GitHub (pinned to 72a37c701e)
Solutions
- Add the matching <anchor path={...} offset={...} /> token
- Use <cursor /> alone for collapsed selections
Example fix
// before
<editor>
<paragraph>hel<focus path={[0,0]} offset={3} />lo</paragraph>
</editor>
// after
<editor>
<paragraph><anchor path={[0,0]} offset={0} />hel<focus path={[0,0]} offset={3} />lo</paragraph>
</editor> Defensive patterns
Strategy: validation
Validate before calling
const anchors = countTokens(value, AnchorToken)
const focuses = countTokens(value, FocusToken)
if (anchors !== focuses) throw new Error('anchor/focus tokens must be paired') Type guard
const isPairedSelectionTokens = (a: number, f: number): boolean => a === f
Try / catch
null
Prevention
- Always emit <anchor/> and <focus/> as a pair
- Use <cursor/> for collapsed selections
- Don't delete one half of a selection pair when editing fixtures
When it happens
Trigger: Writing jsx(<editor>...<focus path={[0,0]} offset={2} />...</editor>) with no anchor token anywhere in the children.
Common situations: Fixtures edited so the anchor was deleted, or copying a selection template and leaving only the focus half.
Related errors
- The <selection> hyperscript tag must have an <anchor> tag as
- The <selection> hyperscript tag must have a <focus> tag as a
- Slate hyperscript ranges must have both `<anchor />` and `<f
- Cannot resolve a Slate range from a DOM event: ${event}
- 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/7e6c266a8211f435.
Report an issue: GitHub.