GraphiteEditor/Graphite · error
Failed to create canvas element
Error message
Failed to create canvas element
What it means
While blitting each rasterized image, the helper calls `document.create_element("canvas")`, which returns `Result<Element, JsValue>` because the DOM method can throw (e.g. `InvalidCharacterError`). The `.expect("Failed to create canvas element")` panics on that. Since "canvas" is always a valid tag name in an HTML document, an `Err` here means the document isn't a normal HTML document (XML/SVG document, polyfilled DOM) or the environment is a partial mock.
Source
Thrown at frontend/wrapper/src/helpers.rs:164
}
new_obj.into()
}
};
let canvases_obj = Object::from(canvases_obj);
for image in image_data {
let (placeholder_id, width, height) = (image.id, image.width, image.height);
let pixels = image.pixels.as_slice();
let canvas_name = placeholder_id.to_string();
let js_key = JsValue::from_str(&canvas_name);
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}");
}View on GitHub (pinned to c507b35645)
Solutions
- Replace the `.expect` with `match`/`let-else` that logs the image id and `continue`s to the next image, matching the graceful style of the surrounding code.
- In tests, run against a real browser DOM instead of partial mocks.
- Ensure the host page is a standard HTML document (no XHTML/XML document mode) where the wrapper is mounted.
- Probe once at startup: `document.createElement('canvas')` succeeds before enabling image-blitting paths.
Example fix
// before
let canvas: HtmlCanvasElement = document
.create_element("canvas")
.expect("Failed to create canvas element")
.dyn_into::<HtmlCanvasElement>()
.expect("Failed to cast element to HtmlCanvasElement");
// after
let canvas = match document.create_element("canvas") {
Ok(element) => element,
Err(err) => {
error!("create_element('canvas') threw {err:?} for image id {placeholder_id}");
continue;
}
};
let Ok(canvas) = canvas.dyn_into::<HtmlCanvasElement>() else {
error!("created element is not an HTMLCanvasElement for image id {placeholder_id}");
continue;
}; Defensive patterns
Strategy: validation
Validate before calling
// TS: startup probe that createElement works before relying on image blitting
export const domCanCreateCanvas: boolean = (() => {
try {
return document.createElement('canvas') instanceof HTMLCanvasElement;
} catch {
return false;
}
})(); Try / catch
JS cannot catch the wasm panic; gate blitting on the startup probe above and check `await editor.hasCrashed()` if the editor stops responding.
Prevention
- Run in a real browser DOM; if using jsdom, configure it fully.
- Ensure the host document is HTML mode, not XML/SVG.
When it happens
Trigger: `render_image_data_to_canvases` running against a document created by `document.implementation.createDocument(null, ...)` (XML mode), a DOM emulation where `createElement` throws or is missing, or a page whose `document` global was replaced.
Common situations: Embedding the editor's canvas blitting in test environments (jsdom variants, happy-dom) or non-HTML host documents; SSR shims with incomplete DOM APIs; rare custom-element registries that throw during creation.
Related errors
- Failed to get canvas context
- Failed to get canvas context
- window should have a document
- Failed to cast element to HtmlCanvasElement
- Failed to draw ellipse
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/d1211156c821e18c.
Report an issue: GitHub.