{"record":{"id":"c0e8babc04bb3858","repo":"BookStackApp/BookStack","slug":"method-is-not-supported-in-headless-mode","errorCode":null,"errorMessage":"${method} is not supported in headless mode","messagePattern":"(.+?) is not supported in headless mode","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"resources/js/wysiwyg/lexical/headless/index.ts","lineNumber":38,"sourceCode":"  editorConfig?: CreateEditorArgs,\n): LexicalEditor {\n  const editor = createEditor(editorConfig);\n  editor._headless = true;\n\n  const unsupportedMethods = [\n    'registerDecoratorListener',\n    'registerRootListener',\n    'registerMutationListener',\n    'getRootElement',\n    'setRootElement',\n    'getElementByKey',\n    'focus',\n    'blur',\n  ] as const;\n\n  unsupportedMethods.forEach((method: typeof unsupportedMethods[number]) => {\n    editor[method] = () => {\n      throw new Error(`${method} is not supported in headless mode`);\n    };\n  });\n\n  return editor;\n}\n","sourceCodeStart":20,"sourceCodeEnd":44,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/resources/js/wysiwyg/lexical/headless/index.ts#L20-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst editor = createHeadlessEditor(config);\neditor.focus(); // throws\n\n// after\nconst editor = createHeadlessEditor(config);\neditor.update(() => { /* manipulate state only */ });","handlingStrategy":"validation","validationCode":"const HEADLESS_UNSUPPORTED = ['focus', 'blur'];\nif (HEADLESS_UNSUPPORTED.includes(methodName)) {\n  throw new SkipHeadlessCall(methodName);\n}\neditor[methodName]();","typeGuard":"function isHeadlessEditor(editor: LexicalEditor): boolean {\n  return (editor as any).__headless === true ||\n    typeof window === 'undefined' || typeof document === 'undefined';\n}","tryCatchPattern":"try {\n  editor.focus();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('is not supported in headless mode')) {\n    return; // expected in headless tests\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["lexical","headless","test-environment","dom"],"backgroundTag":"headless-editor-unsupported-method","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}