{"record":{"id":"21278ac516427c48","repo":"ianstormtaylor/slate","slug":"cannot-get-the-edge-point-in-the-node-at-path","errorCode":null,"errorMessage":"Cannot get the ${edge} point in the node at path [${at}] because it has no ${edge} text node.","messagePattern":"Cannot get the (.+?) point in the node at path \\[(.+?)\\] because it has no (.+?) text node\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slate/src/editor/point.ts","lineNumber":23,"sourceCode":"\nexport const point: EditorInterface['point'] = (editor, at, options = {}) => {\n  const { edge = 'start' } = options\n\n  if (Location.isPath(at)) {\n    let path\n\n    if (edge === 'end') {\n      const [, lastPath] = Node.last(editor, at)\n      path = lastPath\n    } else {\n      const [, firstPath] = Node.first(editor, at)\n      path = firstPath\n    }\n\n    const node = Node.get(editor, path)\n\n    if (!Node.isText(node)) {\n      throw new Error(\n        `Cannot get the ${edge} point in the node at path [${at}] because it has no ${edge} text node.`\n      )\n    }\n\n    return { path, offset: edge === 'end' ? node.text.length : 0 }\n  }\n\n  if (Location.isRange(at)) {\n    const [start, end] = Range.edges(at)\n    return edge === 'start' ? start : end\n  }\n\n  return at\n}\n","sourceCodeStart":5,"sourceCodeEnd":38,"githubUrl":"https://github.com/ianstormtaylor/slate/blob/72a37c701e5da4bb13a305d416d9c070d19d3a45/packages/slate/src/editor/point.ts#L5-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nTransforms.removeNodes(editor, { at: [0, 0] }) // leaves element empty\nconst end = Editor.end(editor, [0]) // throws\n\n// after\nTransforms.removeNodes(editor, { at: [0, 0] })\nif (Node.get(editor, [0]).children.length === 0) {\n  Transforms.insertNodes(editor, { text: '' }, { at: [0, 0] })\n}\nconst end = Editor.end(editor, [0])","handlingStrategy":"validation","validationCode":"const node = Node.get(editor, path)\nif (!Node.isText(node) && node.children?.length > 0) {\n  const end = Editor.end(editor, path)\n}","typeGuard":"const hasTextDescendant = (n) =>\n  !Node.isText(n) && n.children.some(c => Node.isText(c) || c.children?.length)","tryCatchPattern":null,"preventionTips":["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"],"tags":["slate","points","empty-node","text-node","selection"],"backgroundTag":"empty-node-point-error","analyzedSha":"72a37c701e5da4bb13a305d416d9c070d19d3a45","analyzedAt":"2026-08-27T23:04:51.145Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}