{"record":{"id":"e912b4635c4ca4a1","repo":"zed-industries/zed","slug":"getting-offscreencanvas-2d-context-error","errorCode":null,"errorMessage":"getting OffscreenCanvas 2D context: {error:?}","messagePattern":"getting OffscreenCanvas 2D context: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gpui_web/src/canvas_text.rs","lineNumber":43,"sourceCode":"    context: OffscreenCanvasRenderingContext2d,\n}\n\nimpl TextCanvas {\n    fn new() -> Result<Self> {\n        let canvas = OffscreenCanvas::new(1, 1)\n            .map_err(|error| anyhow!(\"creating text OffscreenCanvas: {error:?}\"))?;\n        let options = js_sys::Object::new();\n        // Every rasterized glyph is read back for upload into GPUI's atlas.\n        let assigned = js_sys::Reflect::set(\n            &options,\n            &JsValue::from_str(\"willReadFrequently\"),\n            &JsValue::TRUE,\n        )\n        .map_err(|error| anyhow!(\"setting Canvas readback option: {error:?}\"))?;\n        ensure!(assigned, \"Canvas readback option could not be set\");\n        let context = canvas\n            .get_context_with_context_options(\"2d\", &options)\n            .map_err(|error| anyhow!(\"getting OffscreenCanvas 2D context: {error:?}\"))?\n            .context(\"OffscreenCanvas 2D text rendering is unavailable\")?\n            .dyn_into::<OffscreenCanvasRenderingContext2d>()\n            .map_err(|error| anyhow!(\"unexpected OffscreenCanvas 2D context: {error:?}\"))?;\n        Ok(Self { canvas, context })\n    }\n\n    fn configure(&self, css_font: &str) -> Result<()> {\n        ensure!(!css_font.trim().is_empty(), \"Canvas text font is empty\");\n        // An invalid CSS font assignment is ignored by Canvas. Reset first so\n        // it cannot accidentally inherit the preceding request's font.\n        self.context.set_font(\"10px sans-serif\");\n        self.context.set_font(css_font);\n        self.context.set_text_align(\"left\");\n        self.context.set_text_baseline(\"alphabetic\");\n        self.context.set_fill_style_str(\"white\");\n        // web-sys does not expose direction on the offscreen 2D context.\n        let assigned = js_sys::Reflect::set(\n            self.context.as_ref(),","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/zed-industries/zed/blob/916fc2b8cb3a815cbef4a3b40e13081be72036b6/crates/gpui_web/src/canvas_text.rs#L25-L61","documentation":"After building the options object, TextCanvas::new requests a '2d' context from the OffscreenCanvas via get_context_with_context_options. If the browser throws or returns a JS error, this anyhow error wraps it. This indicates the 2D context could not be created at all (distinct from returning null, which yields the 'unavailable' context error).","triggerScenarios":"Calling get_context_with_context_options(\"2d\", &options) when the engine rejects the call: OffscreenCanvas present but 2D context unsupported, invalid context options, or a JS exception in the call.","commonSituations":"Browser supports OffscreenCanvas but not its 2D context (older Safari 16.x); context options object malformed due to the earlier Reflect failure; browser bugs with willReadFrequently on OffscreenCanvas.","solutions":["Update the browser to a version with full OffscreenCanvas 2D support (Safari 16.4+, Chrome 69+, Firefox 105+).","Retry creating the context without the willReadFrequently option to rule out option-related rejection.","Fall back to a regular HTMLCanvasElement 2D context when OffscreenCanvas 2D is unavailable."],"exampleFix":"// before\nlet context = canvas.get_context_with_context_options(\"2d\", &options)?;\n// after\nlet context = canvas\n    .get_context_with_context_options(\"2d\", &options)\n    .or_else(|_| canvas.get_context(\"2d\"))\n    .context(\"OffscreenCanvas 2D text rendering is unavailable\")?;","handlingStrategy":"fallback","validationCode":"function supportsOffscreenCanvas2d() {\n  try {\n    const c = new OffscreenCanvas(1, 1);\n    return c.getContext(\"2d\") !== null;\n  } catch { return false; }\n}","typeGuard":"fn offscreen_2d_supported(window: &web_sys::Window) -> bool {\n    let canvas = web_sys::OffscreenCanvas::new(1, 1).ok()?;\n    canvas.get_context(\"2d\").ok()?.flatten().is_some()\n}","tryCatchPattern":"match TextCanvas::new(width, height) {\n    Ok(canvas) => canvas,\n    Err(e) if format!(\"{e:#}\").contains(\"2D context\") => switch_to_dom_canvas_backend(),\n    Err(e) => return Err(e),\n};","preventionTips":["Probe for OffscreenCanvas 2D support once at startup before wiring the text backend.","Maintain a DOM-canvas fallback path for older Safari.","Keep browser support matrix documented and CI-test on minimum supported versions."],"tags":["web","wasm","canvas","browser-compatibility"],"backgroundTag":"canvas-context-creation-failed","analyzedSha":"916fc2b8cb3a815cbef4a3b40e13081be72036b6","analyzedAt":"2026-09-19T19:09:50.599Z","contentChangedAt":"2026-09-19T19:09:50.599Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}