eythaann/Seelen-UI · warning
Widget already initialized
Error message
Widget already initialized
What it means
`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()`.
Source
Thrown at libs/core/src/state/widget/mod.ts:226
let oldDPR = globalThis.devicePixelRatio;
await this.webview.setZoom(1 / oldDPR);
this.window.onScaleChanged(() => {
if (globalThis.devicePixelRatio !== 1) {
// when zoom was set dpr changed, so in case of change this is accomulative unit
oldDPR = oldDPR * globalThis.devicePixelRatio;
this.webview.setZoom(1 / oldDPR);
}
});
}
/**
* Will initialize the widget based on the preset and mark it as `pending`, this function won't show the widget.
* This should be called before any other action on the widget. After this you should call
* `ready` to mark the widget as ready and show it.
*/
public async init(options: InitWidgetOptions = {}): Promise<void> {
if (this.runtimeState.initialized) {
console.warn(`Widget already initialized`);
return;
}
this.runtimeState.initialized = true;
this.runtimeState.hwnd = await invoke(SeelenCommand.GetSelfWindowId);
this.destroyOnHide = options.closeOnHide ?? this.def.lazy;
if (options.normalizeDevicePixelRatio) {
await this.normalizeDevicePixelRatio();
}
await initMonitorsState();
await OPTIMISTIC_FRAME.runExclusive(async (state) => {
await state.init(this);
});
if (options.autoSizeByContent) {
this.autoSizer = new WidgetAutoSizer(View on GitHub (pinned to dee4aaa940)
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.
Example fix
// before
const w1 = Widget.getCurrent(); await w1.init();
const w2 = Widget.getCurrent(); await w2.init(); // warns
// after
const widget = Widget.getCurrent();
await widget.init({ closeOnHide: true }); // single call
Defensive patterns
Strategy: try-catch
Validate before calling
const widget = Widget.getCurrent();
// track your own init flag if lifecycle is spread across modules
if (!widget.__myInitDone) {
await widget.init(options);
widget.__myInitDone = true;
} Type guard
function needsInit(widget: Widget): boolean {
// expose runtimeState.initialized or track it app-side
return !(widget as any).runtimeState?.initialized;
} Try / catch
try {
await widget.init(options);
} catch (e) {
if (String(e).includes("already initialized")) {
// idempotent path: proceed with ready()
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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`.
Related errors
- Widget is already ready
- Widget was not initialized before ready
- Widget definition not found for ${currentWidgetId}
- Invalid widget id
AI-assisted analysis of eythaann/Seelen-UI@dee4aaa940 (2026-09-03).
Data as JSON: /api/errors/3f3e0cbed4f2f31a.
Report an issue: GitHub.