{"record":{"id":"46cf28485a777f8d","repo":"facebook/lexical","slug":"empty-inline-elements-are-removed-from-the-editors","errorCode":null,"errorMessage":"Empty inline elements are removed from the EditorState, so returning 'true' from ${node.constructor.name}.canBeEmpty() is not allowed","messagePattern":"Empty inline elements are removed from the EditorState, so returning 'true' from (.+?)\\.canBeEmpty\\(\\) is not allowed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/lexical-extension/src/NormalizeInlineElementsExtension.ts","lineNumber":30,"sourceCode":"  ElementNode,\n  type LexicalNode,\n  safeCast,\n} from 'lexical';\n\nimport {namedSignals} from './namedSignals';\nimport {effect} from './signals';\n\nconst __DEV__ = process.env.NODE_ENV !== 'production';\n\nexport interface NormalizeInlineElementsConfig {\n  disabled: boolean;\n}\n\nfunction deleteEmptyInline(node: LexicalNode) {\n  if ($isElementNode(node) && node.isInline() && node.isEmpty()) {\n    node.remove();\n    if (__DEV__ && node.canBeEmpty()) {\n      console.warn(\n        `Empty inline elements are removed from the EditorState, so returning 'true' from ${node.constructor.name}.canBeEmpty() is not allowed`,\n      );\n    }\n  }\n}\n\n/**\n * This extension removes empty inline nodes from the EditorState.\n * This extension is designed to facilitate a smooth migration from\n * the plugin API with the option to disable it, but it may be removed\n * in the future and integrated into the core\n */\nexport const NormalizeInlineElementsExtension = defineExtension({\n  build: (editor, config, state) => namedSignals(config),\n  config: safeCast<NormalizeInlineElementsConfig>({\n    disabled: false,\n  }),\n  name: '@lexical/NormalizeInlineElements',","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/facebook/lexical/blob/76a22dcba981b46119fcec45f935270707e26a57/packages/lexical-extension/src/NormalizeInlineElementsExtension.ts#L12-L48","documentation":"The NormalizeInlineElementsExtension deletes empty inline ElementNodes because Lexical removes empty inline elements from the EditorState. If such a node also reports canBeEmpty() === true, that is a configuration contradiction — the node declares it may be empty while the runtime guarantee is that it never is — so in dev builds it warns naming the offending class.","triggerScenarios":"deleteEmptyInline's node transform runs on an update where an inline ElementNode ($isElementNode && isInline) is empty; the node is removed and, in __DEV__, canBeEmpty() returns true, triggering the warning.","commonSituations":"Custom inline nodes (e.g. chips, mentions, links) whose class overrides canBeEmpty() to return true while the normalize-inline-elements extension is active; enabling the extension on editors with legacy inline nodes; empty inline elements created by paste or deletions.","solutions":["Override canBeEmpty() to return false on any inline ElementNode subclass used with this extension.","Remove the NormalizeInlineElementsExtension if empty inline elements must be preserved (and handle them yourself).","Audit custom inline nodes after enabling the extension; the warning names the exact class to fix.","Handle empty inline nodes at paste/cleanup time so they never exist in the state."],"exampleFix":"// before\nclass ChipNode extends ElementNode {\n  canBeEmpty() { return true; }\n}\n// after\nclass ChipNode extends ElementNode {\n  canBeEmpty() { return false; }\n}","handlingStrategy":"validation","validationCode":"if ($isElementNode(node) && node.isInline() && node.canBeEmpty()) {\n  console.warn(`${node.constructor.name}: inline + canBeEmpty()=true is invalid with NormalizeInlineElementsExtension`);\n}","typeGuard":"function isRemovableInline(node: LexicalNode): boolean {\n  return $isElementNode(node) && node.isInline() && node.isEmpty();\n}","tryCatchPattern":"null","preventionTips":["Return false from canBeEmpty() on inline ElementNode subclasses.","Don't enable NormalizeInlineElementsExtension if you rely on empty inline nodes.","Add unit tests asserting custom inline nodes' canBeEmpty() is false.","Clean empty inline nodes at paste/transform time."],"tags":["element-node","inline-elements","extension","configuration"],"backgroundTag":"invalid-canbeempty-override","analyzedSha":"76a22dcba981b46119fcec45f935270707e26a57","analyzedAt":"2026-08-31T21:45:54.792Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}