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
- Run the WASM module in a browser main thread (or an environment exposing `window`/`document`), not Node.js or a bare worker.
- If using a worker architecture, do DOM/canvas work on the main thread and only offload computation to the worker.
- Check the bundler/loader target: use a web target (e.g. wasm-bindgen --target web) so init runs on the main thread.
- In tests, use a headless browser (e.g. playwright/wasm-bindgen-test in browser mode) instead of Node.
- 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
- Always load the WASM interpreter on the browser main thread.
- Use wasm-bindgen --target web and a module script, not a Node require.
- Do not run DOM-dependent Slint init inside Web Workers or service workers.
- In CI, test with a headless browser rather than Node.
- Ensure the canvas element with the expected id exists before init runs.
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
- Cannot proceed without WebGL - aborting
- wasm-interpreter: Could not retrieve DOM document
- wasm-interpreter: Could not retrieve existing HTML Canvas…
- Callbacks were set up earlier
- winit backend: Specified DOM element
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)