eythaann/Seelen-UI · error · Error

Widget was not initialized before ready

Error message

Widget was not initialized before ready

What it means

Widget.ready() signals that a widget finished setup and can be shown (unless lazy, where it is shown on a trigger action). The library requires the lifecycle to start with initialization (which computes the decoded webview label and config); calling ready() on an instance whose runtimeState.initialized flag is false means ready() was called out of order, so it throws instead of proceeding with an unconfigured widget.

Source

Thrown at libs/core/src/state/widget/mod.ts:294

    if (options.disableCssAnimations ?? true) {
      await disableAnimationsOnPerformanceMode();
    } else {
      console.trace("Animations won't be disabled because widget configuration");
    }
  }

  /**
   * Will mark the widget as `ready` and pool pending triggers.
   *
   * If the widget is not lazy this will inmediately show the widget.
   * Lazy widget should be shown on trigger action.
   */
  public async ready(options: ReadyWidgetOptions = {}): Promise<void> {
    const { show = !this.def.lazy } = options;

    if (!this.runtimeState.initialized) {
      throw new Error(`Widget was not initialized before ready`);
    }

    if (this.runtimeState.ready) {
      console.warn(`Widget is already ready`);
      return;
    }

    this.runtimeState.ready = true;
    await this.autoSizer?.execute();

    if (show && !(await this.window.isVisible())) {
      await this.show();
    }

    // this will mark the widget as ready, and send pending trigger event if exists
    await invoke(SeelenCommand.SetCurrentWidgetStatus, { status: WidgetStatus.Ready });
  }

View on GitHub (pinned to dee4aaa940)

Solutions

  1. Await init before ready(): await Widget.getCurrent().init(...) then await widget.ready().
  2. Use the singleton from Widget.getCurrent() rather than constructing Widget manually.
  3. Gate ready() on a flag or a promise that resolves after initialization.
  4. Log runtimeState before ready() when debugging order issues.

Example fix

// before: const widget = Widget.getCurrent(); widget.ready(); // throws
// after: const widget = Widget.getCurrent(); await widget.init(); await widget.ready();
Defensive patterns

Strategy: validation

Validate before calling

// track init completion in your bootstrap: let initialized = false; await widget.init(); initialized = true; if (!initialized) throw new Error('call init() before ready()');

Type guard

function isInitialized(w: Widget): boolean { return (w as unknown as { runtimeState: { initialized: boolean } }).runtimeState.initialized; }

Try / catch

try { await widget.ready(); } catch (e) { if (e instanceof Error && e.message.startsWith('Widget was not initialized')) { await widget.init(); await widget.ready(); } else { throw e; } }

Prevention

When it happens

Trigger: Calling widget.ready() before the widget's init step completed; forgetting `await` on init and calling ready() synchronously; creating a second Widget instance manually (bypassing the initialized getCurrent() singleton) and calling ready() on it; calling ready() from module top-level code that races the async init.

Common situations: Restructuring widget entry code and accidentally moving ready() above init; dropping an await during a refactor; using new Widget(...) directly; init triggered by an event that has not fired yet.

Related errors


AI-assisted analysis of eythaann/Seelen-UI@dee4aaa940 (2026-09-03). Data as JSON: /api/errors/c0055a5271998031. Report an issue: GitHub.