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 `<anchor />`. For collapsed selections, use `<cursor />` instead.
What it means
Thrown by hyperscript's createEditor when an <anchor /> token was placed in the value but no matching <focus /> token exists. Slate ranges need both ends; hyperscript enforces the pair (or the collapsed <cursor /> alternative).
Source
Thrown at packages/slate-hyperscript/src/creators.ts:277
}
}
for (const { ref = selection, offset } of getFoci(node)) {
if (offset != null) {
ref.focus = { path, offset }
}
}
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 <focus path={...} offset={...} /> token
- Replace the lone <anchor /> with <cursor /> for a collapsed selection
Example fix
// before
<editor>
<paragraph><anchor path={[0,0]} offset={0} />hello</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
// fixture invariant: count anchor and focus tokens
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
- Review selection tags after refactoring fixtures
When it happens
Trigger: Writing jsx(<editor><paragraph><anchor path={[0,0]} offset={0}/>text</paragraph></editor>) without a focus token.
Common situations: Authoring test editors where only the anchor was added, or where the focus token was accidentally removed during refactor.
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}
- Cannot resolve a DOM point from Slate point: ${Scrubber.stri
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/8eded42d17b00d4e.
Report an issue: GitHub.