BookStackApp/BookStack · error · Error
Can't find options for dropdown menu
Error message
Can't find options for dropdown menu
What it means
The dropdown helper keeps a Map of HTMLElement -> HandleDropdownParams tracking registered dropdown menus and their behavior. getOptions(menu) throws when an event fires for a menu element that was never registered in that map. The framework treats unknown dropdown elements as a programming error rather than silently no-oping.
Source
Thrown at resources/js/wysiwyg/ui/framework/helpers/dropdowns.ts:119
}
protected openDropdown(menu: HTMLElement): void {
const {toggle, showAside, onOpen} = this.getOptions(menu);
menu.hidden = false;
positionMenu(menu, toggle, Boolean(showAside), this.isRTL);
this.openDropdowns.add(menu);
menu.addEventListener('mouseover', this.onMenuMouseOver);
if (onOpen) {
onOpen();
}
}
protected getOptions(menu: HTMLElement): HandleDropdownParams {
const options = this.dropdownOptions.get(menu);
if (!options) {
throw new Error(`Can't find options for dropdown menu`);
}
return options;
}
/**
* Add handling for a new dropdown.
*/
public handle(options: HandleDropdownParams) {
const {menu, toggle, showOnHover} = options;
// Register dropdown
this.dropdownOptions.set(menu, options);
// Configure default events
const toggleShowing = (event: MouseEvent) => {
menu.hasAttribute('hidden') ? this.openDropdown(menu) : this.closeDropdown(menu);
};View on GitHub (pinned to 18f8469a1c)
Solutions
- Ensure every dropdown menu element is registered through the helper's setup/add path before its open/close/toggle handlers can fire.
- If you rebuild or replace the dropdown DOM, re-register the new element with the helper.
- Verify only one dropdown helper instance is in play — handlers must query the same instance that registered the menu.
- Unregister/cleanup elements on teardown so handlers and options are removed together.
Example fix
// before
const menu = document.createElement('div');
dropdowns.toggle(menu); // getOptions(menu) throws: never registered
// after
const menu = document.createElement('div');
dropdowns.addDropdown(menu, { /* HandleDropdownParams */ });
dropdowns.toggle(menu); // safe Defensive patterns
Strategy: validation
Validate before calling
// Verify a menu is registered with the helper before invoking its behavior
function isRegisteredDropdown(helper: DropdownHelper, menu: HTMLElement): boolean {
return helper.hasOptions(menu); // or track registered elements in a local Set
}
if (!isRegisteredDropdown(dropdowns, menu)) {
dropdowns.addDropdown(menu, options); // register first
}
dropdowns.toggle(menu); Try / catch
try {
dropdowns.toggle(menu);
} catch (e) {
if (e instanceof Error && e.message.includes("Can't find options for dropdown menu")) {
// menu element was stale or never registered: re-register or skip
} else { throw e; }
} Prevention
- Always create dropdown behavior through the helper's registration path, never by attaching raw listeners to menu elements.
- Re-register menu elements after any DOM rebuild or framework re-render.
- Clean up (unregister) menus on teardown so late events don't hit a missing entry.
- Avoid instantiating a second dropdown helper instance alongside the editor's own.
When it happens
Trigger: An onOpen/onClose/toggle/showAside handler fires for a dropdown DOM element with no entry in dropdownOptions — e.g. the menu element was created or replaced outside the registration path, the dropdown was unregistered before a late close event, or a second helper instance's handlers query a map they never populated.
Common situations: Custom dropdown buttons wired without going through the register flow; DOM elements rebuilt after registration (stale element references); a close event arriving after teardown removed the options.
Related errors
- Attempted to use EditorUIContext before it has been set
- Context attempted to be used without being set
- Attempted to show modal of key [${key}] but no modal registe
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/93647c2a6f9dd8bb.
Report an issue: GitHub.