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

  1. Override canBeEmpty() to return false on any inline ElementNode subclass used with this extension.
  2. Remove the NormalizeInlineElementsExtension if empty inline elements must be preserved (and handle them yourself).
  3. Audit custom inline nodes after enabling the extension; the warning names the exact class to fix.
  4. 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

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


AI-assisted analysis of facebook/lexical@76a22dcba9 (2026-08-31). Data as JSON: /api/errors/46cf28485a777f8d. Report an issue: GitHub.