facebook/lexical · error
Internal Lexical error: invariant() called without a message
Error message
Internal Lexical error: invariant() called without a message
What it means
Lexical's invariant(cond, message) helper throws a plain Error when its condition is falsy; when it is called without a message argument the error text falls back to the generic 'Internal Lexical error: invariant() called without a message'. This signals an assertion failure inside Lexical's internal code paths (e.g. $getHtmlContent, exportNodeToJSON, $handleTab callers listed) where an assumed precondition about the node tree or selection did not hold. It usually indicates a corrupted or unexpected editor state rather than an API misuse with a documented remedy.
Source
Thrown at packages/lexical-internal/src/invariant.ts:28
// if "condition" is false will throw an error. This function is special-cased
// in flow itself, so we can't name it anything else.
//
// In a production build the `transformErrorMessages` Babel plugin replaces
// every call site with a hoisted `if (!cond)` check plus a
// `formatProdErrorMessage(code, ...args)` call, so this body is only reached
// when the source is consumed without that transform (the `source` export
// condition or an untransformed dev build). It must therefore stand on its
// own: interpolate `%s` placeholders against args and throw.
export default function invariant(
cond?: boolean,
message = 'Internal Lexical error: invariant() called without a message',
...args: string[]
): asserts cond {
if (cond) {
return;
}
throw new Error(
args.reduce((msg, arg) => msg.replace('%s', String(arg)), message),
);
}
View on GitHub (pinned to 76a22dcba9)
Solutions
- Check whether a custom node's methods (createDOM, updateDOM, exportJSON, etc.) violate their contracts and fix the implementation
- Ensure all node classes used in the document are registered on the editor
- Align all @lexical/* package versions (stale/mismatched packages cause inconsistent invariants)
- Reproduce with a minimal editor state and file an issue with the stack trace if it appears to be a Lexical bug
Example fix
// before
exportJSON(): SerializedNode {return {type: 'my-node', ...};} // missing 'version', breaks exportNodeToJSON invariant
// after
exportJSON(): SerializedMyNode {return {...super.exportJSON(), type: 'my-node', version: 1};} Defensive patterns
Strategy: try-catch
Validate before calling
// validate node tree invariants before serialization
editor.read(() => {
$dfs().forEach(({node}) => {
if (!node.getType()) throw new Error('Node missing type: ' + node.getKey());
});
}); Type guard
function isSerializableNode(node: LexicalNode): node is LexicalNode & {exportJSON(): SerializedLexicalNode} {
return typeof (node as {exportJSON?: unknown}).exportJSON === 'function';
} Try / catch
try {
const html = $getHtmlContent();
} catch (e) {
if (String(e).includes('Internal Lexical error')) {
console.error('Lexical invariant violated — check custom nodes and package versions', e);
} else {
throw e;
}
} Prevention
- Implement exportJSON/createDOM/updateDOM exactly per node contract (type, version fields)
- Pin all @lexical/* packages to the same version
- Register every node class present in the document on the editor
- Never feed untrusted/hand-built node JSON without validating shape first
When it happens
Trigger: Any of the calling APIs ($getHtmlContent, $getLexicalContent, exportNodeToJSON, $appendNodesToJSON, $getCodeLines, $handleTab) reaching an internal state that violates its assumptions — e.g. serializing a tree containing a node type that fails an internal assertion, or tab handling on a selection the code did not expect.
Common situations: Custom ElementNode/DecoratorNode implementations that break internal contracts (wrong return types from methods); operating on nodes not registered on the editor; version mismatches between @lexical packages after an upgrade; feeding hand-crafted JSON into $parseSerializedNode.
Related errors
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- ${method} is not supported in headless mode
- HashtagPlugin: HashtagNode not registered on editor
- LinkPlugin: LinkNode not registered on editor
AI-assisted analysis of facebook/lexical@76a22dcba9 (2026-08-31).
Data as JSON: /api/errors/58f52b0fb40b9e6c.
Report an issue: GitHub.