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

  1. Remove the editor.focus()/blur() (or other unsupported method) call when running headless.
  2. Branch on editor type: only call DOM methods when the editor was created with a real DOM (e.g. guard with typeof document !== 'undefined').
  3. If DOM behavior is truly needed, use a full editor with a JSDom-injected document/window in tests instead of createHeadlessEditor.
  4. 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

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


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/c0e8babc04bb3858. Report an issue: GitHub.