facebook/lexical · error
${method} is not supported in headless mode
Error message
${method} is not supported in headless mode What it means
createHeadlessEditor wraps a normal Lexical editor but replaces DOM-oriented methods (like focus, blur, and related methods listed in unsupportedMethods) with functions that always throw, because a headless editor has no root element or browser DOM to interact with. Headless editors are for server-side serialization, parsing, and transforms only. Calling any DOM-lifecycle method on one is a programming mistake, so the library fails fast with this message.
Source
Thrown at packages/lexical-headless/src/index.ts:36
editorConfig?: CreateEditorArgs,
): LexicalEditor {
const editor = createEditor(editorConfig);
editor._headless = true;
const unsupportedMethods = [
'registerDecoratorListener',
'registerRootListener',
'registerMutationListener',
'getRootElement',
'setRootElement',
'getElementByKey',
'focus',
'blur',
] as const;
unsupportedMethods.forEach((method: (typeof unsupportedMethods)[number]) => {
editor[method] = () => {
throw new Error(`${method} is not supported in headless mode`);
};
});
return editor;
}
View on GitHub (pinned to 76a22dcba9)
Solutions
- Use createEditor (browser) instead of createHeadlessEditor when you need focus/blur behavior
- Remove or guard focus()/blur() calls when running in headless/test environments
- Use environment detection to skip DOM-only setup code for headless editors
Example fix
// before
const editor = createHeadlessEditor({nodes});
editor.focus(); // throws: focus is not supported in headless mode
// after
const editor = isHeadless ? createHeadlessEditor({nodes}) : createEditor({nodes});
if (!isHeadless) editor.focus(); Defensive patterns
Strategy: try-catch
Validate before calling
function supportsDom(editor: LexicalEditor): boolean {
return editor._rootElement !== null || !('isHeadless' in editor && editor.isHeadless);
}
// only call focus/blur when running a real (non-headless) editor Type guard
function isHeadlessEditor(editor: LexicalEditor): boolean {
return (editor as {_headless?: boolean})._headless === true;
} Try / catch
try {
editor.focus();
} catch (e) {
if (String(e).includes('not supported in headless mode')) {
// expected in headless/test environment; skip DOM behavior
} else {
throw e;
}
} Prevention
- Keep headless editors confined to server/test/serialization code paths
- Centralize focus/blur calls in helpers that check the environment first
- When sharing setup code, branch on whether the editor has a rootElement
When it happens
Trigger: Invoking editor.focus(), editor.blur(), or another stubbed DOM method directly on an editor produced by createHeadlessEditor, or calling a library/plugin that internally calls those methods.
Common situations: Reusing a headless editor (built for Node/ssr tests) in browser UI code; running shared editor-setup helpers that call focus() after mount against a headless instance; SSR tests importing plugins that auto-focus.
Related errors
- Cell not found at cords.
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- Internal Lexical error: invariant() called without a message
- HashtagPlugin: HashtagNode not registered on editor
AI-assisted analysis of facebook/lexical@76a22dcba9 (2026-08-31).
Data as JSON: /api/errors/61eae6a7f6f11d20.
Report an issue: GitHub.