{"record":{"id":"e9cb4c7f7687716a","repo":"facebook/lexical","slug":"node-at-cords-not-tablecellnode","errorCode":null,"errorMessage":"Node at cords not TableCellNode.","messagePattern":"Node at cords not TableCellNode\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/lexical-table/src/LexicalTableNode.ts","lineNumber":791,"sourceCode":"\n    const node = $getNearestNodeFromDOMNode(cell.elem);\n\n    if ($isTableCellNode(node)) {\n      return node;\n    }\n\n    return null;\n  }\n\n  getCellNodeFromCordsOrThrow(\n    x: number,\n    y: number,\n    table: TableDOMTable,\n  ): TableCellNode {\n    const node = this.getCellNodeFromCords(x, y, table);\n\n    if (!node) {\n      throw new Error('Node at cords not TableCellNode.');\n    }\n\n    return node;\n  }\n\n  getRowStriping(): boolean {\n    return Boolean(this.getLatest().__rowStriping);\n  }\n\n  setRowStriping(newRowStriping: boolean): this {\n    const self = this.getWritable();\n    self.__rowStriping = newRowStriping;\n    return self;\n  }\n\n  setFrozenColumns(columnCount: number): this {\n    const self = this.getWritable();\n    self.__frozenColumnCount = columnCount;","sourceCodeStart":773,"sourceCodeEnd":809,"githubUrl":"https://github.com/facebook/lexical/blob/76a22dcba981b46119fcec45f935270707e26a57/packages/lexical-table/src/LexicalTableNode.ts#L773-L809","documentation":"This accessor resolves coordinates to a TableCellNode via getCellNodeFromCords and throws 'Node at cords not TableCellNode.' when the lookup returns null. Unlike error 8, the DOM cell may exist but the corresponding node in the editor tree could not be resolved as a TableCellNode, typically due to a mismatch between the DOM table snapshot and the current node tree.","triggerScenarios":"Calling it with coordinates whose resolved key no longer maps to a live TableCellNode (cell deleted in a concurrent update); passing a TableDOMTable from a previous render; using it inside a read while a transform is mutating the table.","commonSituations":"Custom paste/merge plugins racing with table transforms; tables inside collaborative editing where another client removed cells; code reusing a TableDOMTable reference across update boundaries.","solutions":["Perform the lookup inside the same editor.update/read as the event that computed coordinates","Recompute the TableDOMTable from the current DOM instead of caching it","Use the non-throwing getCellNodeFromCords and handle null explicitly","Ensure TableCellNode is registered on the editor so node resolution works"],"exampleFix":"// before\neditor.read(() => {\n  const node = table.getCellNodeAtCords(x, y, cachedDomTable); // throws on stale table\n});\n\n// after\neditor.read(() => {\n  const node = table.getCellNodeFromCords(x, y, table.getDOMCellFromCords ? currentDomTable : domTable);\n  if (node) { /* handle */ }\n});","handlingStrategy":"try-catch","validationCode":"const node = table.getCellNodeFromCords(x, y, domTable); // non-throwing variant\nif (node && $isTableCellNode(node)) { /* proceed */ }","typeGuard":"function isLiveTableCell(node: LexicalNode | null | undefined): node is TableCellNode {\n  return $isTableCellNode(node) && node.isAttached();\n}","tryCatchPattern":"try {\n  const node = table.getCellNodeAtCords(x, y, domTable);\n} catch (e) {\n  if (String(e).includes('Node at cords not TableCellNode')) {\n    // DOM snapshot out of sync with node tree — recompute inside current update\n  } else { throw e; }\n}","preventionTips":["Prefer getCellNodeFromCords (null-returning) over the throwing wrapper","Check node.isAttached() before using resolved table cells","In collaborative editing, re-resolve coordinates after remote table mutations"],"tags":["lexical","table","coordinates","node-resolution"],"backgroundTag":"cell-not-found-in-table","analyzedSha":"76a22dcba981b46119fcec45f935270707e26a57","analyzedAt":"2026-08-31T21:45:54.792Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}