facebook/lexical · warning
Empty inline elements are removed from the EditorState, so r
Error message
Empty inline elements are removed from the EditorState, so returning 'true' from ${node.constructor.name}.canBeEmpty() is not allowed What it means
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.
Source
Thrown at packages/lexical-extension/src/NormalizeInlineElementsExtension.ts:30
ElementNode,
type LexicalNode,
safeCast,
} from 'lexical';
import {namedSignals} from './namedSignals';
import {effect} from './signals';
const __DEV__ = process.env.NODE_ENV !== 'production';
export interface NormalizeInlineElementsConfig {
disabled: boolean;
}
function deleteEmptyInline(node: LexicalNode) {
if ($isElementNode(node) && node.isInline() && node.isEmpty()) {
node.remove();
if (__DEV__ && node.canBeEmpty()) {
console.warn(
`Empty inline elements are removed from the EditorState, so returning 'true' from ${node.constructor.name}.canBeEmpty() is not allowed`,
);
}
}
}
/**
* This extension removes empty inline nodes from the EditorState.
* This extension is designed to facilitate a smooth migration from
* the plugin API with the option to disable it, but it may be removed
* in the future and integrated into the core
*/
export const NormalizeInlineElementsExtension = defineExtension({
build: (editor, config, state) => namedSignals(config),
config: safeCast<NormalizeInlineElementsConfig>({
disabled: false,
}),
name: '@lexical/NormalizeInlineElements',View on GitHub (pinned to 76a22dcba9)
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.
Example fix
// before
class ChipNode extends ElementNode {
canBeEmpty() { return true; }
}
// after
class ChipNode extends ElementNode {
canBeEmpty() { return false; }
} Defensive patterns
Strategy: validation
Validate before calling
if ($isElementNode(node) && node.isInline() && node.canBeEmpty()) {
console.warn(`${node.constructor.name}: inline + canBeEmpty()=true is invalid with NormalizeInlineElementsExtension`);
} Type guard
function isRemovableInline(node: LexicalNode): boolean {
return $isElementNode(node) && node.isInline() && node.isEmpty();
} Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- $createTextNodesFromYText: Node ${type} is not registered
- Unrecognized charset
- Override for ${name} specifies 'replace' without 'withKlass'
AI-assisted analysis of facebook/lexical@76a22dcba9 (2026-08-31).
Data as JSON: /api/errors/46cf28485a777f8d.
Report an issue: GitHub.