eythaann/Seelen-UI · error · Error

LazyRune was not initialized

Error message

LazyRune was not initialized

What it means

LazyRune is the Svelte 5 counterpart of LazySignal: it computes its value via an async initializer executed by init(), and reading .value before initialization would return undefined while breaking reactivity expectations. The getter therefore throws until a value has been set (by init() resolving or a direct set).

Source

Thrown at libs/ui/svelte/utils/LazyRune.svelte.ts:45

 *   console.log(colors.value);
 * });
 * ```
 */
export class LazyRune<T> {
  private _value = $state<T>();
  private initialized = false;

  constructor(private initializer: () => Promise<T> | T) {
    this.setByPayload = this.setByPayload.bind(this);
  }

  /**
   * Gets the current value. Throws error if not initialized yet.
   * This property is reactive and will trigger updates in Svelte components.
   */
  get value(): T {
    if (!this.initialized) {
      throw new Error("LazyRune was not initialized");
    }
    return this._value as T;
  }

  /**
   * Sets the value and marks as initialized.
   * This will trigger reactivity in Svelte components.
   */
  set value(value: T) {
    this.initialized = true;
    this._value = value;
  }

  /**
   * Will call the initializer and set the value if not already set
   * via another setters.
   *
   * This uses a double-check pattern to prevent race conditions:

View on GitHub (pinned to dee4aaa940)

Solutions

  1. Await rune.init() at startup (top-level await in the entry or in an $effect) before any read.
  2. Gate dependent components on an initialized flag or render children only after init resolves.
  3. Check init() is awaited, not fire-and-forget.
  4. Use a fallback accessor: rune.initialized ? rune.value : fallbackValue.

Example fix

// before: const $items = lazyRune(() => invoke(GetItems)); console.log($items.value); // throws
// after: const $items = lazyRune(() => invoke(GetItems)); await $items.init(); console.log($items.value); // ok
Defensive patterns

Strategy: validation

Validate before calling

if (!$items.initialized) { await $items.init(); } const items = $items.value;

Type guard

function isInitializedRune<T>(r: LazyRune<T> & { initialized: boolean }): boolean { return r.initialized; }

Try / catch

try { render($items.value); } catch (e) { if (e instanceof Error && e.message === 'LazyRune was not initialized') { await $items.init(); render($items.value); } else { throw e; } }

Prevention

When it happens

Trigger: Reading $rune.value before calling init(); not awaiting init() and reading the value in the same synchronous flow; a Svelte component reading the rune during first render before the init effect ran; module-level reads at import time.

Common situations: Forgetting init() after refactoring to lazyRune; multiple components consuming a rune where only one was supposed to call init; racing $effect init with synchronous template reads; consuming a shared rune from another module assuming self-initialization.

Related errors


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