BookStackApp/BookStack · error · Error

Could not find expected color bar in the icon for this

Error message

Could not find expected color bar in the icon for this ${this.definition.label} button

What it means

EditorColorButton.getColorBar looks up the SVG color-bar element inside the button's icon via the selector 'svg .editor-icon-color-bar'. If the button's rendered DOM does not contain that element (missing class on the inner SVG rect/path), the method throws. It is called by updateState on every selection change, so an icon template missing the class breaks the whole toolbar update.

Solutions

  1. Ensure the button's icon SVG includes an element with class 'editor-icon-color-bar' (e.g. <rect class="editor-icon-color-bar" .../>).
  2. Only call getColorBar after the button is mounted (getDOMElement() returns rendered content); guard updateState until DOM is ready.
  3. If icons are customized, copy the stock color-well icon markup and keep the editor-icon-color-bar class intact.
  4. Defensively check the selector result and no-op instead of throwing when the icon intentionally has no color bar.
  5. Check changelogs after upgrading the editor UI framework for icon markup changes.

Example fix

// before
getColorBar(): HTMLElement {
    const colorBar = this.getDOMElement().querySelector('svg .editor-icon-color-bar');
    if (!colorBar) {
        throw new Error(`Could not find expected color bar in the icon for this ${this.definition.label} button`);
    }
    return (colorBar as HTMLElement);
}
// after
getColorBar(): HTMLElement | null {
    return this.getDOMElement().querySelector<HTMLElement>('svg .editor-icon-color-bar');
}
// and in updateState:
const colorBar = this.getColorBar();
if (colorBar) colorBar.setAttribute('fill', value);
Defensive patterns

Strategy: type-guard

Validate before calling

function hasColorBar(button) {
  return button.getDOMElement()?.querySelector('svg .editor-icon-color-bar') != null;
}

Type guard

function isColorBar(el: Element | null | undefined): el is HTMLElement {
  return el instanceof HTMLElement;
}

Try / catch

try {
  const colorBar = this.getColorBar();
  colorBar.setAttribute('fill', value);
} catch (e) {
  if (String(e.message).startsWith('Could not find expected color bar')) {
    // icon template lacks the color bar; skip fill sync
  } else throw e;
}

Prevention

When it happens

Trigger: The button definition's icon HTML lacks an element with class 'editor-icon-color-bar' (e.g. custom icon SVG replaced without the color-bar element), getColorBar is called before the button's DOMElement is mounted/rendered, or the icon markup was changed in a template update so the querySelector returns null.

Common situations: Customizing toolbar icons in a CMS/template and dropping the editor-icon-color-bar class; a theme or icon pack swap; calling getColorBar (or updateState) before the button is attached to the DOM; version upgrade renaming the icon markup while custom overrides still use old markup.

Related errors


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

Appendix: source

Thrown at resources/js/wysiwyg/ui/framework/blocks/color-button.ts:19

import {EditorBasicButtonDefinition, EditorButton} from "../buttons";
import {EditorUiStateUpdate} from "../core";
import {$isRangeSelection} from "lexical";
import {$getSelectionStyleValueForProperty} from "@lexical/selection";

export class EditorColorButton extends EditorButton {
    protected style: string;

    constructor(definition: EditorBasicButtonDefinition, style: string) {
        super(definition);

        this.style = style;
    }

    getColorBar(): HTMLElement {
        const colorBar = this.getDOMElement().querySelector('svg .editor-icon-color-bar');

        if (!colorBar) {
            throw new Error(`Could not find expected color bar in the icon for this ${this.definition.label} button`);
        }

        return (colorBar as HTMLElement);
    }

    updateState(state: EditorUiStateUpdate): void {
        super.updateState(state);

        if ($isRangeSelection(state.selection)) {
            const value = $getSelectionStyleValueForProperty(state.selection, this.style);
            const colorBar = this.getColorBar();
            colorBar.setAttribute('fill', value);
        }
    }

}

View on GitHub (pinned to 18f8469a1c)