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
- Give 2D image-data blitting its own canvas element; never reuse a canvas that wgpu/WebGL has taken a context on
- Narrow before casting: use dyn_ref::<CanvasRenderingContext2d>() and log an error instead of panicking when the type does not match
- Avoid transferControlToOffscreen on canvases used by this code path, or bind to OffscreenCanvasRenderingContext2D instead
- 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
- Keep one canvas per backend: 2D blitting and wgpu/WebGL surfaces on separate elements
- Treat dyn_into on DOM objects as fallible; prefer dyn_ref plus logging in all new code
- Never transferControlToOffscreen a canvas that later code calls get_context("2d") on
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
- Failed to cast context to CanvasRenderingContext2d
- Failed to cast element to HtmlCanvasElement
- Failed to draw arc
- Failed to get canvas context
- Context should be a canvas 2d context
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/e91686f332bb97b9.
Report an issue: GitHub.