GraphiteEditor/Graphite · error

Failed to cast context to CanvasRenderingContext2d

Error message

Failed to cast context to CanvasRenderingContext2d

What it means

This panic fires in render_image_data_to_canvases in the wasm wrapper: after canvas.get_context("2d") returns a value, dyn_into::<CanvasRenderingContext2d>() requires that JS object to be an instance of the standard 2D context class. The lookup succeeded but the returned object has the wrong type, so wasm-bindgen refuses the cast. Typical causes are a canvas whose context was already created in another mode (webgl/webgpu), an offscreen 2D context, or a polyfilled canvas.

Source

Thrown at frontend/wrapper/src/helpers.rs:176

		if Reflect::has(&canvases_obj, &js_key).unwrap_or(false) || width == 0 || height == 0 {
			continue;
		}

		let canvas: HtmlCanvasElement = document
			.create_element("canvas")
			.expect("Failed to create canvas element")
			.dyn_into::<HtmlCanvasElement>()
			.expect("Failed to cast element to HtmlCanvasElement");

		canvas.set_width(width);
		canvas.set_height(height);

		let context: CanvasRenderingContext2d = canvas
			.get_context("2d")
			.expect("Failed to get 2d context")
			.expect("2d context was not found")
			.dyn_into::<CanvasRenderingContext2d>()
			.expect("Failed to cast context to CanvasRenderingContext2d");
		let clamped_pixels = wasm_bindgen::Clamped(pixels);
		match ImageData::new_with_u8_clamped_array_and_sh(clamped_pixels, width, height) {
			Ok(image_data_obj) => {
				if context.put_image_data(&image_data_obj, 0, 0).is_err() {
					error!("Failed to put image data on canvas for id: {placeholder_id}");
				}
			}
			Err(e) => {
				error!("Failed to create ImageData for id: {placeholder_id}: {e:?}");
			}
		}

		let js_value = JsValue::from(canvas);

		if Reflect::set(&canvases_obj, &js_key, &js_value).is_err() {
			error!("Failed to set canvas '{canvas_name}' on imageCanvases object");
		}
	}

View on GitHub (pinned to c507b35645)

Solutions

  1. Give 2D image-data blitting its own canvas element; never reuse a canvas that wgpu/WebGL has taken a context on
  2. Narrow before casting: use dyn_ref::<CanvasRenderingContext2d>() and log an error instead of panicking when the type does not match
  3. Avoid transferControlToOffscreen on canvases used by this code path, or bind to OffscreenCanvasRenderingContext2D instead
  4. In test environments, run against real browser canvases (for example Playwright) rather than jsdom stubs

Example fix

// before
let context: CanvasRenderingContext2d = canvas
	.get_context("2d")
	.expect("Failed to get 2d context")
	.expect("2d context was not found")
	.dyn_into::<CanvasRenderingContext2d>()
	.expect("Failed to cast context to CanvasRenderingContext2d");

// after
let Some(ctx) = canvas.get_context("2d").ok().flatten() else {
	error!("2d context unavailable for placeholder {placeholder_id}");
	return;
};
let Ok(context) = ctx.dyn_into::<CanvasRenderingContext2d>() else {
	error!("context for placeholder {placeholder_id} is not CanvasRenderingContext2d");
	return;
};
Defensive patterns

Strategy: type-guard

Validate before calling

// before drawing, confirm the canvas can still yield a usable 2D context value
canvas.get_context("2d").ok().flatten().is_some();

Type guard

fn as_2d_context(value: &JsValue) -> Option<CanvasRenderingContext2d> {
	value.dyn_ref::<CanvasRenderingContext2d>().cloned()
}

Try / catch

match ctx_value.dyn_into::<CanvasRenderingContext2d>() {
	Ok(context) => blit(context, image_data),
	Err(value) => error!("unexpected context type: {:?}", value.js_typeof()),
}

Prevention

When it happens

Trigger: Calling get_context("2d") on a canvas that wgpu or WebGL already acquired a context on; a canvas moved to offscreen via transferControlToOffscreen so getContext returns an OffscreenCanvasRenderingContext2D; running under jsdom or canvas polyfills that return non-standard objects.

Common situations: Blitting rasterized node-graph output onto a canvas that is also used as a wgpu render target; wasm unit tests under Node/jsdom; browsers or extensions overriding HTMLCanvasElement.prototype.getContext.

Related errors


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