{"record":{"id":"beea4b510d8e74ee","repo":"GraphiteEditor/Graphite","slug":"context-should-be-a-canvas-2d-context","errorCode":null,"errorMessage":"Context should be a canvas 2d context","messagePattern":"Context should be a canvas 2d context","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"editor/src/messages/portfolio/document/overlays/utility_types_web.rs","lineNumber":1028,"sourceCode":"\n\t\tself.render_context.set_fill_style_str(color);\n\t\tself.render_context.fill();\n\t}\n\n\t/// Fills the area inside the path with a pattern. Assumes `color` is an sRGB hex string.\n\t/// Used by the fill tool to show the area to be filled.\n\tpub fn fill_path_pattern(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2, color: &str) {\n\t\tconst PATTERN_WIDTH: usize = 4;\n\t\tconst PATTERN_HEIGHT: usize = 4;\n\n\t\tlet pattern_canvas = OffscreenCanvas::new(PATTERN_WIDTH as u32, PATTERN_HEIGHT as u32).unwrap();\n\t\tlet pattern_context: OffscreenCanvasRenderingContext2d = pattern_canvas\n\t\t\t.get_context(\"2d\")\n\t\t\t.ok()\n\t\t\t.flatten()\n\t\t\t.expect(\"Failed to get canvas context\")\n\t\t\t.dyn_into()\n\t\t\t.expect(\"Context should be a canvas 2d context\");\n\n\t\t// 4x4 pixels, 4 components (RGBA) per pixel\n\t\tlet mut data = [0_u8; 4 * PATTERN_WIDTH * PATTERN_HEIGHT];\n\n\t\tlet rgba = hex_to_rgba_u8(color);\n\n\t\t// ┌▄▄┬──┬──┬──┐\n\t\t// ├▀▀┼──┼──┼──┤\n\t\t// ├──┼──┼▄▄┼──┤\n\t\t// ├──┼──┼▀▀┼──┤\n\t\t// └──┴──┴──┴──┘\n\t\tlet pixels = [(0, 0), (2, 2)];\n\t\tfor &(x, y) in &pixels {\n\t\t\tlet index = (x + y * PATTERN_WIDTH) * 4;\n\t\t\tdata[index..index + 4].copy_from_slice(&rgba);\n\t\t}\n\n\t\tlet image_data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(wasm_bindgen::Clamped(&data), PATTERN_WIDTH as u32, PATTERN_HEIGHT as u32).unwrap();","sourceCodeStart":1010,"sourceCodeEnd":1046,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/overlays/utility_types_web.rs#L1010-L1046","documentation":"After get_context(\"2d\") succeeds, dyn_into::<OffscreenCanvasRenderingContext2d>() performs an unchecked-at-compile-time JS type downcast and this .expect(\"Context should be a canvas 2d context\") panics if the returned JsValue is not actually an OffscreenCanvasRenderingContext2d. That happens when the runtime returns a different object for \"2d\" (a plain CanvasRenderingContext2D from a polyfill, or an incomplete OffscreenCanvas implementation). In fully compliant browsers this is effectively unreachable.","triggerScenarios":"A browser or polyfill returns a non-OffscreenCanvas 2D context object from OffscreenCanvas.getContext('2d'), causing JsCast::dyn_into to fail and the expect to panic.","commonSituations":"Running the web editor under legacy polyfills (core-js/ OffscreenCanvas shims), WebViews with half-implemented OffscreenCanvas, or wasm-bindgen/web-sys version mismatches that change the expected JS class.","solutions":["Use dyn_ref::<OffscreenCanvasRenderingContext2d>() to try the downcast without panicking, logging and bailing on mismatch","Pin consistent web-sys/wasm-bindgen versions so the Rust-side type matches the shipped JS classes","Test on the oldest supported browser matrix to catch partial OffscreenCanvas implementations"],"exampleFix":"// before\n.dyn_into()\n.expect(\"Context should be a canvas 2d context\");\n\n// after\nlet Ok(pattern_context) = ctx.dyn_into::<OffscreenCanvasRenderingContext2d>() else {\n\tlog::error!(\"2D context was not an OffscreenCanvasRenderingContext2d\");\n\treturn;\n};","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn as_offscreen_2d(value: &wasm_bindgen::JsValue) -> bool {\n\tvalue.is_instance_of::<web_sys::OffscreenCanvasRenderingContext2d>()\n}","tryCatchPattern":"match ctx.dyn_into::<OffscreenCanvasRenderingContext2d>() {\n\tOk(typed) => { /* use typed context */ }\n\tErr(value) => log::error!(\"unexpected 2D context type: {value:?}\"),\n}","preventionTips":["Use dyn_ref/dyn_into as a checked downcast and handle the Err arm instead of expecting","Keep web-sys and wasm-bindgen versions aligned with the browser APIs you target","Smoke-test canvas paths in the oldest browser of your support matrix"],"tags":["rust","wasm-bindgen","jscast","offscreencanvas","type-mismatch"],"backgroundTag":"wasm-bindgen-type-mismatch","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}