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
- Await rune.init() at startup (top-level await in the entry or in an $effect) before any read.
- Gate dependent components on an initialized flag or render children only after init resolves.
- Check init() is awaited, not fire-and-forget.
- 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
- Await rune.init() in the entry point or an $effect before any component reads it.
- Designate a single owner component responsible for init().
- Never read .value at module scope on import.
- Expose shared runes through a class with getters (repo convention) that can guard on initialized.
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
- LazySignal was not initialized
- Widget was not initialized before ready
- The library is being used on a non Seelen UI environment
- no translation for key "${key}"
- no key provided to $t()
AI-assisted analysis of eythaann/Seelen-UI@dee4aaa940 (2026-09-03).
Data as JSON: /api/errors/32aa6fe040e1ead9.
Report an issue: GitHub.