{"record":{"id":"3f3e0cbed4f2f31a","repo":"eythaann/Seelen-UI","slug":"widget-already-initialized","errorCode":null,"errorMessage":"Widget already initialized","messagePattern":"Widget already initialized","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"libs/core/src/state/widget/mod.ts","lineNumber":226,"sourceCode":"    let oldDPR = globalThis.devicePixelRatio;\n    await this.webview.setZoom(1 / oldDPR);\n    this.window.onScaleChanged(() => {\n      if (globalThis.devicePixelRatio !== 1) {\n        // when zoom was set dpr changed, so in case of change this is accomulative unit\n        oldDPR = oldDPR * globalThis.devicePixelRatio;\n        this.webview.setZoom(1 / oldDPR);\n      }\n    });\n  }\n\n  /**\n   * Will initialize the widget based on the preset and mark it as `pending`, this function won't show the widget.\n   * This should be called before any other action on the widget. After this you should call\n   * `ready` to mark the widget as ready and show it.\n   */\n  public async init(options: InitWidgetOptions = {}): Promise<void> {\n    if (this.runtimeState.initialized) {\n      console.warn(`Widget already initialized`);\n      return;\n    }\n\n    this.runtimeState.initialized = true;\n    this.runtimeState.hwnd = await invoke(SeelenCommand.GetSelfWindowId);\n    this.destroyOnHide = options.closeOnHide ?? this.def.lazy;\n\n    if (options.normalizeDevicePixelRatio) {\n      await this.normalizeDevicePixelRatio();\n    }\n\n    await initMonitorsState();\n    await OPTIMISTIC_FRAME.runExclusive(async (state) => {\n      await state.init(this);\n    });\n\n    if (options.autoSizeByContent) {\n      this.autoSizer = new WidgetAutoSizer(","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/eythaann/Seelen-UI/blob/dee4aaa94066c5d0888ab25554864862fc47be15/libs/core/src/state/widget/mod.ts#L208-L244","documentation":"`Widget.init()` guards against double initialization: if `runtimeState.initialized` is already true it logs `Widget already initialized` (console.warn, not a throw) and returns early. The library expects `init()` to be called exactly once, before any other widget action, followed by `ready()`.","triggerScenarios":"Calling `Widget.getCurrent().init(...)` twice — e.g. init logic in a module that is evaluated twice (HMR re-import, duplicated entry script), or calling both an app-level bootstrap and a component-level init on the same widget instance.","commonSituations":"Vite HMR re-running the entry module during development; mounting the widget in two places; a migration where old bootstrap code still calls `init` alongside the new `Widget.getCurrent().init`.","solutions":["Call `init()` exactly once at the widget entry point; remove duplicate init calls.","If re-initialization is intentional (e.g. HMR), create a new widget instance or reset `runtimeState` instead of reusing the initialized one.","Treat the warning as benign if the early-return behavior is desired; check whether the second init's options (e.g. `closeOnHide`) were meant to apply and hoist them into the single init call."],"exampleFix":"// before\nconst w1 = Widget.getCurrent(); await w1.init();\nconst w2 = Widget.getCurrent(); await w2.init(); // warns\n// after\nconst widget = Widget.getCurrent();\nawait widget.init({ closeOnHide: true }); // single call\n","handlingStrategy":"try-catch","validationCode":"const widget = Widget.getCurrent();\n// track your own init flag if lifecycle is spread across modules\nif (!widget.__myInitDone) {\n  await widget.init(options);\n  widget.__myInitDone = true;\n}","typeGuard":"function needsInit(widget: Widget): boolean {\n  // expose runtimeState.initialized or track it app-side\n  return !(widget as any).runtimeState?.initialized;\n}","tryCatchPattern":"try {\n  await widget.init(options);\n} catch (e) {\n  if (String(e).includes(\"already initialized\")) {\n    // idempotent path: proceed with ready()\n  } else throw e;\n}","preventionTips":["Call init() once, from a single entry-point module.","Beware HMR re-executing entry modules during development.","Keep all init options in the single init call rather than re-calling init to change them."],"tags":["widget","lifecycle","double-initialization","hmr"],"backgroundTag":"already-initialized","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"}