slint-ui/slint · critical

wasm-interpreter: Could not retrieve DOM window

Error message

wasm-interpreter: Could not retrieve DOM window

What it means

The WASM interpreter's init retrieves the browser DOM window via web_sys::window() and panics if it is None, because the backend needs the window to locate the HTML canvas element. web_sys::window() returns None when the code is not running in a browser main context, so this panic indicates the runtime environment fundamentally lacks DOM access.

Solutions

  1. Run the WASM module in a browser main thread (or an environment exposing `window`/`document`), not Node.js or a bare worker.
  2. If using a worker architecture, do DOM/canvas work on the main thread and only offload computation to the worker.
  3. Check the bundler/loader target: use a web target (e.g. wasm-bindgen --target web) so init runs on the main thread.
  4. In tests, use a headless browser (e.g. playwright/wasm-bindgen-test in browser mode) instead of Node.
  5. Polyfills that fake `window` are insufficient — the backend needs a real DOM canvas; use OffscreenCanvas-capable integration only if the backend supports it.

Example fix

// before (Node test)
const slint = await import('./slint_interpreter.js');
await slint.default();
// after (browser main thread via wasm-bindgen web target)
<script type="module">
  import init from './slint_interpreter.js';
  await init(); // window/document available
</script>
Defensive patterns

Strategy: fallback

Validate before calling

// JS host, before calling init()
if (typeof window === 'undefined' || typeof document === 'undefined') {
    throw new Error('slint-interpreter requires a browser main thread; got ' +
      (typeof window === 'undefined' ? 'no window' : 'no document'));
}

Type guard

// JS host
function hasDomAccess() {
  try { return typeof window !== 'undefined' && !!window.document && !!window.document.createElement; }
  catch { return false; }
}

Try / catch

// JS host
try {
  await init();
} catch (e) {
  if (String(e).includes('DOM window')) {
    console.error('Load the WASM interpreter in a browser main thread, not Node/worker.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the WASM interpreter's exported init() from a non-browser JS context: Node.js, a web worker without DOM access, or a service worker.

Common situations: Running the slint-interpreter WASM bundle under Node in unit tests, loading it in a Web Worker expecting it to render, or misconfigured bundler targets (node target instead of web).

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/9b3bed8f12ead1eb. Report an issue: GitHub.

Appendix: source

Thrown at api/wasm-interpreter/src/lib.rs:387

thread_local!(
    static NEXT_CANVAS_ID: Rc<RefCell<Option<String>>> = Default::default();
);

#[wasm_bindgen(start)]
pub fn init() -> Result<(), JsValue> {
    #[cfg(feature = "console_error_panic_hook")]
    console_error_panic_hook::set_once();
    let backend = i_slint_backend_winit::Backend::builder()
        .with_spawn_event_loop(true)
        .with_window_attributes_hook(|mut attrs| {
            NEXT_CANVAS_ID.with(|next_id| {
                if let Some(canvas_id) = next_id.borrow_mut().take() {
                    use i_slint_backend_winit::winit::platform::web::WindowAttributesExtWebSys;

                    use wasm_bindgen::JsCast;

                    let html_canvas = web_sys::window()
                        .expect("wasm-interpreter: Could not retrieve DOM window")
                        .document()
                        .expect("wasm-interpreter: Could not retrieve DOM document")
                        .get_element_by_id(&canvas_id)
                        .unwrap_or_else(|| {
                            panic!(
                                "wasm-interpreter: Could not retrieve existing HTML Canvas element '{}'",
                                canvas_id
                            )
                        })
                        .dyn_into::<web_sys::HtmlCanvasElement>()
                        .unwrap_or_else(|_| {
                            panic!(
                                "winit backend: Specified DOM element '{}' is not a HTML Canvas",
                                canvas_id
                            )
                        });
                    attrs = attrs
                        .with_canvas(Some(html_canvas))

View on GitHub (pinned to bb937076de)