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

  1. Run canvas-dependent node code on the browser main thread
  2. In workers, target OffscreenCanvas and access globals through globalThis instead of window
  3. 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

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


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/fa3eecf6d473c158. Report an issue: GitHub.