BookStackApp/BookStack · error · Error
${method} is not supported in headless mode
Error message
${method} is not supported in headless mode What it means
createHeadlessEditor builds a LexicalEditor for use without a browser DOM. After creating the editor it deliberately overwrites DOM-interacting methods (focus, blur, etc.) so each throws this error when called. It is a guard: headless editors have no DOM representation, so these operations are meaningless and would silently misbehave otherwise.
Source
Thrown at resources/js/wysiwyg/lexical/headless/index.ts:38
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 18f8469a1c)
Solutions
- Remove the editor.focus()/blur() (or other unsupported method) call when running headless.
- Branch on editor type: only call DOM methods when the editor was created with a real DOM (e.g. guard with typeof document !== 'undefined').
- If DOM behavior is truly needed, use a full editor with a JSDom-injected document/window in tests instead of createHeadlessEditor.
- Use @testing-library/dom or jsdom globals so a regular editor can be instantiated in the test environment.
Example fix
// before
const editor = createHeadlessEditor(config);
editor.focus(); // throws
// after
const editor = createHeadlessEditor(config);
editor.update(() => { /* manipulate state only */ }); Defensive patterns
Strategy: validation
Validate before calling
const HEADLESS_UNSUPPORTED = ['focus', 'blur'];
if (HEADLESS_UNSUPPORTED.includes(methodName)) {
throw new SkipHeadlessCall(methodName);
}
editor[methodName](); Type guard
function isHeadlessEditor(editor: LexicalEditor): boolean {
return (editor as any).__headless === true ||
typeof window === 'undefined' || typeof document === 'undefined';
} Try / catch
try {
editor.focus();
} catch (e) {
if (e instanceof Error && e.message.includes('is not supported in headless mode')) {
return; // expected in headless tests
}
throw e;
} Prevention
- Keep DOM-simulation calls (focus/blur) out of shared editor utilities used by tests
- Route all editor interactions through commands that work headless
- Assert the editor type in helpers that touch the DOM
When it happens
Trigger: Calling any of the unsupported methods (e.g. editor.focus(), editor.blur()) on the editor instance returned by createHeadlessEditor(). The method list is fixed in resources/js/wysiwyg/lexical/headless/index.ts.
Common situations: Unit tests that reuse editor-utility code written for the browser against a headless editor; test setup helpers that call focus() to simulate user interaction; shared hooks or commands that assume a DOM-backed editor.
Related errors
- To use $generateHtmlFromNodes in headless mode please initia
- Table Element Not Found
- Expected to find TableElement in DOM
- ${error.toString()} Parent: ${dom.tagName}, new child: {tag:
- Cannot call set() on a frozen Lexical node map
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/c0e8babc04bb3858.
Report an issue: GitHub.