facebook/lexical · warning

${name} should implement "importJSON" method to ensure JSON

Error message

${name} should implement "importJSON" method to ensure JSON and default HTML serialization works as expected

What it means

During createEditor node validation, a registered node class without its own static `importJSON` is warned about. Without importJSON, JSON serialization round-trips (editorState.toJSON → parseEditorState) and default HTML serialization will not restore this node correctly, so Lexical warns to keep serialization working as expected.

Source

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

            `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,
      });
    }
  }
  const editor = new LexicalEditor(

View on GitHub (pinned to 76a22dcba9)

Solutions

  1. Add `static importJSON(json: SerializedNode): ThisNode` that constructs the node via $create factory and calls node.updateFromJSON(json) (or applies each field).
  2. If serialization is irrelevant for this node, still provide a minimal importJSON for safety.
  3. Pair it with exportJSON to guarantee a complete round trip.

Example fix

// before
class MyNode extends TextNode {
  static getType() { return 'my-node'; }
  static clone(node: MyNode) { return new MyNode(node.__text, node.__key); }
}
// after
class MyNode extends TextNode {
  static getType() { return 'my-node'; }
  static clone(node: MyNode) { return new MyNode(node.__text, node.__key); }
  static importJSON(json: SerializedMyNode): MyNode {
    return $createMyNode(json.text).updateFromJSON(json);
  }
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Object.prototype.hasOwnProperty.call(MyNode, 'importJSON')) {
  throw new Error('MyNode must implement static importJSON for serialization');
}

Type guard

function hasImportJSON(klass: any): klass is {importJSON(json: any): any} {
  return Object.prototype.hasOwnProperty.call(klass, 'importJSON') && typeof klass.importJSON === 'function';
}

Prevention

When it happens

Trigger: Registering a custom node class via createEditor({nodes: [...]}) (or a nested editor) that lacks a static importJSON method; triggered right after the getType/clone checks for each node class.

Common situations: Custom nodes created before importJSON became expected; nodes only ever created programmatically and never deserialized, then later persisted; copy-pasted node templates missing importJSON.

Related errors


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