facebook/lexical · warning
Override for ${name} specifies 'replace' without 'withKlass'
Error message
Override for ${name} specifies 'replace' without 'withKlass'. 'withKlass' will be required in a future version. What it means
When createEditor processes node overrides that use the legacy `replace` option without a `withKlass`, Lexical cannot statically know which class the override replaces, so it warns that 'withKlass' will become required. The override still works today, but the behavior is deprecated and will break in a future major version.
Source
Thrown at packages/lexical/src/LexicalEditor.ts:1022
// For the side-effect of filling in the static methods
void getStaticNodeConfig(klass);
// Ensure custom nodes implement required methods and replaceWithKlass is instance of base klass.
if (__DEV__) {
// ArtificialNode__DO_NOT_USE can get renamed, so we use the type
const name = klass.name;
const nodeType =
hasOwnStaticMethod(klass, 'getType') && klass.getType();
if (replaceWithKlass) {
invariant(
replaceWithKlass.prototype instanceof klass,
"%s doesn't extend the %s",
replaceWithKlass.name,
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')) {View on GitHub (pinned to 76a22dcba9)
Solutions
- Add withKlass to the override, naming the class being replaced: { replace: ..., withKlass: OriginalNode }.
- Where possible, replace the legacy override pattern with a proper node subclass registered via nodes: or an extension.
- Search the codebase for `replace:` node overrides and update each one.
- Watch the Lexical changelog for the version where withKlass becomes mandatory.
Example fix
// before
override: { replace: true, extend: klass }
// after
override: { replace: true, withKlass: klass, extend: klass } Defensive patterns
Strategy: validation
Validate before calling
for (const [name, o] of Object.entries(nodeOverrides)) {
if ('replace' in o && !('withKlass' in o)) {
console.warn(`Override ${name} uses legacy replace; add withKlass before next major.`);
}
} Type guard
function hasWithKlass(o: object): o is { withKlass: Klass<LexicalNode> } {
return 'withKlass' in o;
} Try / catch
null
Prevention
- Always pair replace: with withKlass in node overrides.
- Prefer proper subclasses/extensions over replace overrides.
- Grep CI for `replace:` overrides lacking withKlass.
- Track the changelog for when withKlass becomes required.
When it happens
Trigger: createEditor (or buildEditorFromExtensions config) is given an entry like { replace: SomeNode, ... } (or override with replace: true) lacking the withKlass property, and validation reaches the `else if (replace)` branch.
Common situations: Upgrading Lexical and porting old node override configs; copy-pasting deprecated override examples from older docs; third-party extensions emitting legacy replace overrides.
Related errors
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- $createTextNodesFromYText: Node ${type} is not registered
- Unrecognized charset
- Empty inline elements are removed from the EditorState, so r
AI-assisted analysis of facebook/lexical@76a22dcba9 (2026-08-31).
Data as JSON: /api/errors/a9bfa34e1dc743a1.
Report an issue: GitHub.