ianstormtaylor/slate · error · Error
Cannot get the previous path of a root path [${path}], becau
Error message
Cannot get the previous path of a root path [${path}], because it has no previous index. What it means
Path.previous() returns the preceding sibling path by decrementing the last index. The root path [] has no last index, so there is no previous sibling and Slate throws. Note this checks only the root; a path like [0] returns [-1], which is invalid but does not throw here — bounds checks are the caller's job.
Source
Thrown at packages/slate/src/interfaces/path.ts:366
case 'split_node':
case 'move_node':
return true
default:
return false
}
},
parent(path: Path): Path {
if (path.length === 0) {
throw new Error(`Cannot get the parent path of the root path [${path}].`)
}
return path.slice(0, -1)
},
previous(path: Path): Path {
if (path.length === 0) {
throw new Error(
`Cannot get the previous path of a root path [${path}], because it has no previous index.`
)
}
const last = path[path.length - 1]
if (last <= 0) {
throw new Error(
`Cannot get the previous path of a first child path [${path}] because it would result in a negative index.`
)
}
return path.slice(0, -1).concat(last - 1)
},
relative(path: Path, ancestor: Path): Path {
if (!Path.isAncestor(ancestor, path) && !Path.equals(path, ancestor)) {
throw new Error(View on GitHub (pinned to 72a37c701e)
Solutions
- Guard before decrementing: if (path.length === 0) stop — and also stop when the last index reaches 0 to avoid producing [-1].
- Bound reverse loops by the first sibling: while (lastIndex >= 0) { visit(...path, lastIndex); lastIndex-- } or compare against Path.parent's children length.
- Prefer built-in traversals (Node.nodes with reverse: true) which handle sibling boundaries correctly.
- Add explicit root checks in any code that chains Path.parent then Path.previous.
Example fix
// before
let p = somePath
while (true) { visit(p); p = Path.previous(p) } // throws on []
// after
let p = somePath
while (p.length > 0 && p[p.length - 1] >= 0 && Editor.hasPath(editor, p)) {
visit(p)
p = Path.previous(p)
} Defensive patterns
Strategy: validation
Validate before calling
if (path.length === 0 || path[path.length - 1] === 0) { /* no previous sibling */ } Type guard
const hasPrevSibling = (p: Path): boolean => p.length > 0 && p[p.length - 1] > 0
Prevention
- Stop reverse sibling loops at the first sibling (last index 0), not just at the root.
- Prefer Node.nodes with reverse: true over manual previous() walking.
When it happens
Trigger: Calling Path.previous([]) directly; reverse iteration walking siblings upward without a root guard; calling Path.previous(Path.parent(p)) when p had length 1, yielding the root path first.
Common situations: Iterating siblings backwards (for (let q = last; ; q = Path.previous(q))) without stopping at the first sibling or the root; loop conditions that assume previous() returns null/undefined at the boundary instead of throwing; porting traversal code that used next() and forgetting the asymmetry.
Related errors
- Cannot get the next path of a root path [${path}], because i
- Unable to find the path for Slate node: ${Scrubber.stringify
- Cannot get the next node from the root node!
- Cannot get the previous node from the root node!
- Cannot get the ancestor node at path [${path}] because it re
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/ab993215f4aed610.
Report an issue: GitHub.