facebook/lexical · warning

${name} must implement static "${method}" method

Error message

${name} must implement static "${method}" method

What it means

When createEditor processes the `nodes` array, each node class must define its own static `getType` and `clone` methods (inherited ones are rejected via hasOwnStaticMethod, except LexicalNode itself). If a class lacks one, Lexical logs this warning; such a node will misbehave (getType/clone falls back to the parent's, producing wrong types or broken cloning).

Source

Thrown at packages/lexical/src/LexicalEditor.ts:1037

            name,
          );
        } else if (replace) {
          console.warn(
            `Override for ${name} specifies 'replace' without 'withKlass'. 'withKlass' will be required in a future version.`,
          );
        }
        if (
          name !== 'RootNode' &&
          nodeType !== 'root' &&
          nodeType !== 'artificial' &&
          // This is mostly for the unit test suite which
          // uses LexicalNode in an otherwise incorrect way
          // by mocking its static getType
          klass !== LexicalNode
        ) {
          (['getType', 'clone'] as const).forEach(method => {
            if (!hasOwnStaticMethod(klass, method)) {
              console.warn(`${name} must implement static "${method}" method`);
            }
          });
          if (!hasOwnStaticMethod(klass, 'importJSON')) {
            console.warn(
              `${name} should implement "importJSON" method to ensure JSON and default HTML serialization works as expected`,
            );
          }
        }
      }
      const type = klass.getType();
      const transforms = getTransformSetFromKlass(klass);
      registeredNodes.set(type, {
        exportDOM: html && html.export ? html.export.get(klass) : undefined,
        klass,
        replace,
        replaceWithKlass,
        sharedNodeState: createSharedNodeState(nodes[i]),
        transforms,

View on GitHub (pinned to 76a22dcba9)

Solutions

  1. Add `static getType(): string` returning a unique type string to the node class.
  2. Add `static clone(node): SameNode` returning a new instance cloned from `node`.
  3. Ensure the class is registered in the editor's nodes array only once and truly extends LexicalNode.
  4. If this is a mock in tests, define the statics explicitly instead of relying on the base class.

Example fix

// before
class MyNode extends TextNode {}
// after
class MyNode extends TextNode {
  static getType(): string {
    return 'my-node';
  }
  static clone(node: MyNode): MyNode {
    return new MyNode(node.__text, node.__key);
  }
}
Defensive patterns

Strategy: type-guard

Validate before calling

function assertNodeStatics(klass: any) {
  for (const m of ['getType', 'clone']) {
    if (!Object.prototype.hasOwnProperty.call(klass, m)) {
      throw new Error(`${klass.name} must implement static "${m}"`);
    }
  }
}

Type guard

function hasOwnStaticMethod(klass: Function, method: string): boolean {
  return Object.prototype.hasOwnProperty.call(klass, method) && typeof (klass as any)[method] === 'function';
}

Prevention

When it happens

Trigger: Passing a custom node class in createEditor({nodes: [...]}) (or nestedEditor node arrays) that extends a Lexical node but does not declare `static getType()` or `static clone()` itself — e.g. a mock or a class relying on inheritance.

Common situations: Hand-rolled CustomNode extending TextNode/ElementNode with only instance methods; test mocks subclassing LexicalNode; classes compiled/transpiled in a way that drops statics; older node definitions predating the clone() requirement.

Related errors


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