ianstormtaylor/slate · error · Error
Cannot get the ${edge} point in the node at path [${at}] bec
Error message
Cannot get the ${edge} point in the node at path [${at}] because it has no ${edge} text node. What it means
Editor.point(editor, at, { edge }) computes the start or end point of a node by finding its first/last text node. If the node at that path is not (or does not contain) a text node — e.g. an empty element with no children — the edge point cannot be computed, so it throws.
Source
Thrown at packages/slate/src/editor/point.ts:23
export const point: EditorInterface['point'] = (editor, at, options = {}) => {
const { edge = 'start' } = options
if (Location.isPath(at)) {
let path
if (edge === 'end') {
const [, lastPath] = Node.last(editor, at)
path = lastPath
} else {
const [, firstPath] = Node.first(editor, at)
path = firstPath
}
const node = Node.get(editor, path)
if (!Node.isText(node)) {
throw new Error(
`Cannot get the ${edge} point in the node at path [${at}] because it has no ${edge} text node.`
)
}
return { path, offset: edge === 'end' ? node.text.length : 0 }
}
if (Location.isRange(at)) {
const [start, end] = Range.edges(at)
return edge === 'start' ? start : end
}
return at
}
View on GitHub (pinned to 72a37c701e)
Solutions
- Ensure elements always contain at least one empty text node ({ text: '' }) — Slate's default normalization normally enforces this, so check custom normalizers/transforms that empty children
- Guard with Editor.hasPath or check Node.get(...).children?.length before computing the point
- Use editor.selection or Range.end on an existing valid range instead of deriving a point from an empty node
Example fix
// before
Transforms.removeNodes(editor, { at: [0, 0] }) // leaves element empty
const end = Editor.end(editor, [0]) // throws
// after
Transforms.removeNodes(editor, { at: [0, 0] })
if (Node.get(editor, [0]).children.length === 0) {
Transforms.insertNodes(editor, { text: '' }, { at: [0, 0] })
}
const end = Editor.end(editor, [0]) Defensive patterns
Strategy: validation
Validate before calling
const node = Node.get(editor, path)
if (!Node.isText(node) && node.children?.length > 0) {
const end = Editor.end(editor, path)
} Type guard
const hasTextDescendant = (n) => !Node.isText(n) && n.children.some(c => Node.isText(c) || c.children?.length)
Prevention
- Keep at least one { text: '' } child in every element
- Don't strip default normalization that enforces non-empty elements
- Check node children before computing edge points on freshly created/emptied nodes
When it happens
Trigger: Calling Editor.point(editor, path, { edge: 'start' }) where the node at path is an empty element (children: []); calling Editor.start/Editor.end on a void element rendered with no text; passing a path deeper than the actual structure so Node.get resolves to a non-text node.
Common situations: Inserting a new empty block and immediately computing its end point to place the caret; normalizers creating empty elements; selections referencing nodes emptied by deletion.
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}
- Cannot resolve a Slate range from DOM range: ${domRange}
- The <selection> hyperscript tag must have an <anchor> tag as
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/21278ac516427c48.
Report an issue: GitHub.