GraphiteEditor/Graphite · error
should have a window in this context
Error message
should have a window in this context
What it means
CanvasImpl::new calls web_sys::window() to reach the document for creating a canvas element; window() returns None whenever the global object is not a Window — web workers expose self rather than window, and Node has neither. Creating a canvas in such an environment panics at this first lookup.
Source
Thrown at node-graph/libraries/canvas-utils/src/wasm.rs:153
},
source_texture.size(),
);
surface_texture.queue.submit([encoder.finish()]);
surface_texture.present();
}
}
/// A wgpu surface backed by an HTML canvas element.
/// Holds a reference to the canvas to prevent garbage collection.
pub struct CanvasImpl {
canvas_id: u64,
canvas: HtmlCanvasElement,
}
impl CanvasImpl {
fn new() -> Self {
let document = window().expect("should have a window in this context").document().expect("window should have a document");
let canvas: HtmlCanvasElement = document.create_element("canvas").unwrap().dyn_into::<HtmlCanvasElement>().unwrap();
let canvas_id = CANVAS_IDS.fetch_add(1, Ordering::SeqCst);
// Store the canvas in the global scope so it doesn't get garbage collected
let window = window().expect("should have a window in this context");
let window_obj = Object::from(window);
let image_canvases_key = JsValue::from_str(CANVASES_OBJECT_KEY);
let mut canvases = Reflect::get(&window_obj, &image_canvases_key);
if canvases.is_err() || canvases.as_ref().map_or(false, |v| v.is_undefined() || v.is_null()) {
Reflect::set(&window_obj.clone(), &image_canvases_key, &Object::new()).unwrap();
canvases = Reflect::get(&window_obj, &image_canvases_key);
}
// Convert key and value to JsValue
let js_key = JsValue::from_str(canvas_id.to_string().as_str());View on GitHub (pinned to c507b35645)
Solutions
- Run canvas-dependent node code on the browser main thread
- In workers, target OffscreenCanvas and access globals through globalThis instead of window
- For tests, run under a DOM environment (jsdom) or gate canvas creation behind a main-thread check
Example fix
// before
let document = window().expect("should have a window in this context").document().expect("window should have a document");
// after
let Some(window) = window() else {
panic!("cannot create a canvas outside a browser window; run on the main thread or use OffscreenCanvas")
};
let document = window.document().expect("window should have a document"); Defensive patterns
Strategy: validation
Validate before calling
fn has_browser_window() -> bool {
web_sys::window().is_some()
} Prevention
- Keep canvas-backed node evaluation on the browser main thread
- In workers, use OffscreenCanvas with globalThis instead of window
- Run wasm tests under a DOM-providing runtime before touching canvas code
When it happens
Trigger: Instantiating canvas-backed nodes inside a web worker; running the wasm module under Node without a DOM shim; server-side evaluation of the module during SSR passes.
Common situations: Moving node graph evaluation off the main thread; wasm tests executed in worker-based runtimes; Node scripts that load the editor binary for rendering.
Related errors
- No global `window` exists
- Failed to call `requestAnimationFrame`
- Failed to call `setTimeout`
- window should have a document
- Failed to fetch Wasm binary part (status ${failedResponse.st
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/fa3eecf6d473c158.
Report an issue: GitHub.