{"record":{"id":"e1ccfc420bf5580b","repo":"GraphiteEditor/Graphite","slug":"failed-to-cast-element-to-htmlcanvaselement","errorCode":null,"errorMessage":"Failed to cast element to HtmlCanvasElement","messagePattern":"Failed to cast element to HtmlCanvasElement","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/wrapper/src/helpers.rs","lineNumber":166,"sourceCode":"\t\t}\n\t};\n\tlet canvases_obj = Object::from(canvases_obj);\n\n\tfor image in image_data {\n\t\tlet (placeholder_id, width, height) = (image.id, image.width, image.height);\n\t\tlet pixels = image.pixels.as_slice();\n\t\tlet canvas_name = placeholder_id.to_string();\n\t\tlet js_key = JsValue::from_str(&canvas_name);\n\n\t\tif Reflect::has(&canvases_obj, &js_key).unwrap_or(false) || width == 0 || height == 0 {\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet canvas: HtmlCanvasElement = document\n\t\t\t.create_element(\"canvas\")\n\t\t\t.expect(\"Failed to create canvas element\")\n\t\t\t.dyn_into::<HtmlCanvasElement>()\n\t\t\t.expect(\"Failed to cast element to HtmlCanvasElement\");\n\n\t\tcanvas.set_width(width);\n\t\tcanvas.set_height(height);\n\n\t\tlet context: CanvasRenderingContext2d = canvas\n\t\t\t.get_context(\"2d\")\n\t\t\t.expect(\"Failed to get 2d context\")\n\t\t\t.expect(\"2d context was not found\")\n\t\t\t.dyn_into::<CanvasRenderingContext2d>()\n\t\t\t.expect(\"Failed to cast context to CanvasRenderingContext2d\");\n\t\tlet clamped_pixels = wasm_bindgen::Clamped(pixels);\n\t\tmatch ImageData::new_with_u8_clamped_array_and_sh(clamped_pixels, width, height) {\n\t\t\tOk(image_data_obj) => {\n\t\t\t\tif context.put_image_data(&image_data_obj, 0, 0).is_err() {\n\t\t\t\t\terror!(\"Failed to put image data on canvas for id: {placeholder_id}\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tErr(e) => {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/frontend/wrapper/src/helpers.rs#L148-L184","documentation":"After `document.create_element(\"canvas\")` succeeds, the wrapper converts the JS value to a typed `HtmlCanvasElement` with `dyn_into`, which performs a JS `instanceof`-style check. The `.expect(\"Failed to cast element to HtmlCanvasElement\")` panics when the created object is not actually an `HTMLCanvasElement` — possible when the document is not an HTML document (XML/SVG documents produce generic elements) or a polyfilled DOM returns a mock that fails the brand check.","triggerScenarios":"Running `render_image_data_to_canvases` in an XML/SVG-mode document or DOM emulation where `createElement('canvas')` returns an object failing `instanceof HTMLCanvasElement`; web-sys and the actual host DOM disagreeing on element interfaces (heavy polyfills, patched globals).","commonSituations":"DOM-emulation test setups (jsdom variants returning generic Element mocks); editors embedded into SVG or XML host documents; environments where `HTMLCanvasElement` is polyfilled without proper branding.","solutions":["Use `let Ok(canvas) = element.dyn_into::<HtmlCanvasElement>() else { ... continue; }` so one uncastable element skips one image instead of crashing.","Ensure the wrapper runs in a standard HTML document in a real browser.","In tests, prefer a real browser runner; if using jsdom, verify `document.createElement('canvas') instanceof HTMLCanvasElement` holds.","Feature-detect before the loop: bail out early if a probe canvas fails the `instanceof` check."],"exampleFix":"// before\nlet canvas: HtmlCanvasElement = document\n  .create_element(\"canvas\")\n  .expect(\"Failed to create canvas element\")\n  .dyn_into::<HtmlCanvasElement>()\n  .expect(\"Failed to cast element to HtmlCanvasElement\");\n\n// after\nlet element = document.create_element(\"canvas\").unwrap_or_else(|err| {\n  panic!(\"create_element('canvas') threw {err:?}\")\n});\nlet Ok(canvas) = element.dyn_into::<HtmlCanvasElement>() else {\n  error!(\"element is not an HTMLCanvasElement; skipping image id {placeholder_id}\");\n  continue;\n};","handlingStrategy":"type-guard","validationCode":"// TS: verify the environment yields real canvas elements\nexport const realCanvasElements: boolean = (() => {\n  try {\n    return document.createElement('canvas') instanceof HTMLCanvasElement;\n  } catch {\n    return false;\n  }\n})();","typeGuard":"function isHtmlCanvasElement(el: unknown): el is HTMLCanvasElement {\n  return typeof HTMLCanvasElement !== 'undefined' && el instanceof HTMLCanvasElement;\n}","tryCatchPattern":null,"preventionTips":["Probe instanceof HTMLCanvasElement once at startup in test/embedding environments.","Prefer real browsers over DOM emulations for anything exercising canvas blitting."],"tags":["wasm-bindgen","jscast","canvas","wasm","panic"],"backgroundTag":"wasm-bindgen-jscast-failed","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}