{"record":{"id":"30ba562c0014fe42","repo":"facebook/lexical","slug":"expected-tablenode","errorCode":null,"errorMessage":"Expected TableNode.","messagePattern":"Expected TableNode\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/lexical-table/src/LexicalTableObserver.ts","lineNumber":590,"sourceCode":"      : null;\n\n    cellNodes.forEach((cellNode: TableCellNode) => {\n      anchor.set(cellNode.getKey(), 0, 'element');\n      focus.set(cellNode.getKey(), cellNode.getChildrenSize(), 'element');\n      formatSelection.formatText(type, alignFormatWith);\n    });\n\n    $setSelection(selection);\n\n    this.editor.dispatchCommand(SELECTION_CHANGE_COMMAND);\n  }\n\n  $clearText() {\n    const {editor} = this;\n    const tableNode = $getNodeByKey(this.tableNodeKey);\n\n    if (!$isTableNode(tableNode)) {\n      throw new Error('Expected TableNode.');\n    }\n\n    const selection = $getSelection();\n\n    invariant($isTableSelection(selection), 'Expected TableSelection');\n\n    const selectedNodes = selection.getNodes().filter($isTableCellNode);\n\n    // Check if the entire table is selected by verifying first and last cells\n    const firstRow = tableNode.getFirstChild();\n    const lastRow = tableNode.getLastChild();\n\n    const isEntireTableSelected =\n      selectedNodes.length > 0 &&\n      firstRow !== null &&\n      lastRow !== null &&\n      $isTableRowNode(firstRow) &&\n      $isTableRowNode(lastRow) &&","sourceCodeStart":572,"sourceCodeEnd":608,"githubUrl":"https://github.com/facebook/lexical/blob/76a22dcba981b46119fcec45f935270707e26a57/packages/lexical-table/src/LexicalTableObserver.ts#L572-L608","documentation":"TableObserver.$clearText() looks up the table node by the observer's stored tableNodeKey with $getNodeByKey. If the key no longer resolves to a live TableNode (undefined or a different node kind), this guard throws. It means the observer is operating against a table that has been removed from the current editor state (e.g. after an undo, transform, or selection change left stale state).","triggerScenarios":"Calling $clearTable at a time when the TableNode keyed by this.tableNodeKey has been removed or replaced: the node was deleted in the pending update, the key became stale after undo/revert, or a node transform moved/replaced the table while a clear operation was in flight.","commonSituations":"Dispatching CLEAR_TABLE_COMMAND after deleting the table in the same update; collaborating editors where the table was removed remotely; custom transforms that recreate TableNodes (new keys) while the observer still holds the old key.","solutions":["Check the table still exists before dispatching the clear: editor.read(() => $getNodeByKey(key) !== undefined) or re-derive the TableNode from the current selection.","Do not hold TableObserver/tableNodeKey references across update boundaries; obtain the table fresh from the current selection.","If the table was legitimately deleted, skip the clear instead of treating it as an error.","In collaboration setups, wrap remote-sync-driven operations so removals received from Yjs invalidate pending local table operations."],"exampleFix":"// before\nobserver.$clearText();\n// after\neditor.update(() => {\n  const tableNode = $getNodeByKey(observer.tableNodeKey);\n  if ($isTableNode(tableNode)) {\n    observer.$clearText();\n  }\n});","handlingStrategy":"validation","validationCode":"const stillValid = editor.read(() => $isTableNode($getNodeByKey(key)));","typeGuard":"function isLiveTable(key: NodeKey, editor: LexicalEditor): boolean {\n  return editor.read(() => $isTableNode($getNodeByKey(key)));\n}","tryCatchPattern":"try {\n  editor.update(() => $clearTable());\n} catch (e) {\n  if (e instanceof Error && e.message === 'Expected TableNode.') return; // table already gone\n  throw e;\n}","preventionTips":["Never cache TableObserver or node-key references across update boundaries","Re-derive the table from the current selection before mutations","Disable table commands when the selection no longer intersects a table"],"tags":["lexical-table","stale-node-reference","selection"],"backgroundTag":"stale-node-reference","analyzedSha":"76a22dcba981b46119fcec45f935270707e26a57","analyzedAt":"2026-08-31T21:45:54.792Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}