{"record":{"id":"32aa6fe040e1ead9","repo":"eythaann/Seelen-UI","slug":"lazyrune-was-not-initialized","errorCode":null,"errorMessage":"LazyRune was not initialized","messagePattern":"LazyRune was not initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"libs/ui/svelte/utils/LazyRune.svelte.ts","lineNumber":45,"sourceCode":" *   console.log(colors.value);\n * });\n * ```\n */\nexport class LazyRune<T> {\n  private _value = $state<T>();\n  private initialized = false;\n\n  constructor(private initializer: () => Promise<T> | T) {\n    this.setByPayload = this.setByPayload.bind(this);\n  }\n\n  /**\n   * Gets the current value. Throws error if not initialized yet.\n   * This property is reactive and will trigger updates in Svelte components.\n   */\n  get value(): T {\n    if (!this.initialized) {\n      throw new Error(\"LazyRune was not initialized\");\n    }\n    return this._value as T;\n  }\n\n  /**\n   * Sets the value and marks as initialized.\n   * This will trigger reactivity in Svelte components.\n   */\n  set value(value: T) {\n    this.initialized = true;\n    this._value = value;\n  }\n\n  /**\n   * Will call the initializer and set the value if not already set\n   * via another setters.\n   *\n   * This uses a double-check pattern to prevent race conditions:","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/eythaann/Seelen-UI/blob/dee4aaa94066c5d0888ab25554864862fc47be15/libs/ui/svelte/utils/LazyRune.svelte.ts#L27-L63","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: const $items = lazyRune(() => invoke(GetItems)); console.log($items.value); // throws\n// after: const $items = lazyRune(() => invoke(GetItems)); await $items.init(); console.log($items.value); // ok","handlingStrategy":"validation","validationCode":"if (!$items.initialized) { await $items.init(); } const items = $items.value;","typeGuard":"function isInitializedRune<T>(r: LazyRune<T> & { initialized: boolean }): boolean { return r.initialized; }","tryCatchPattern":"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; } }","preventionTips":["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."],"tags":["initialization","async","svelte","state"],"backgroundTag":"signal-read-before-init","analyzedSha":"dee4aaa94066c5d0888ab25554864862fc47be15","analyzedAt":"2026-09-03T10:20:37.842Z","contentChangedAt":"2026-09-03T10:20:37.842Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}