{"record":{"id":"4a50f21009d6786a","repo":"zed-industries/zed","slug":"canvas-text-direction-could-not-be-set","errorCode":null,"errorMessage":"Canvas text direction could not be set","messagePattern":"Canvas text direction could not be set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gpui_web/src/canvas_text.rs","lineNumber":66,"sourceCode":"    }\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(),\n            &JsValue::from_str(\"direction\"),\n            &JsValue::from_str(\"ltr\"),\n        )\n        .map_err(|error| anyhow!(\"setting Canvas text direction: {error:?}\"))?;\n        ensure!(assigned, \"Canvas text direction could not be set\");\n        Ok(())\n    }\n}\n\nfn with_canvas<T>(operation: impl FnOnce(&mut TextCanvas) -> Result<T>) -> Result<T> {\n    CANVAS.with(|canvas| {\n        let mut canvas = canvas\n            .try_borrow_mut()\n            .context(\"Canvas text renderer was called reentrantly\")?;\n        if canvas.is_none() {\n            *canvas = Some(TextCanvas::new()?);\n        }\n        operation(\n            canvas\n                .as_mut()\n                .context(\"Canvas text renderer is unavailable\")?,\n        )\n    })","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/zed-industries/zed/blob/916fc2b8cb3a815cbef4a3b40e13081be72036b6/crates/gpui_web/src/canvas_text.rs#L48-L84","documentation":"Raised in `TextCanvas::configure` when assigning `direction = \"ltr\"` on the OffscreenCanvasRenderingContext2d via `js_sys::Reflect::set` completes without an exception but returns `false`, meaning the property write was rejected. The library forces left-to-right direction for deterministic text measurement, and treats a rejected assignment as fatal since subsequent text metrics would be unreliable. This mirrors the readback-option check in `new` and indicates an unusual JS environment or a context object that rejects property writes.","triggerScenarios":"The rendering context object is frozen/sealed or wrapped in a proxy that rejects writes, the JS engine does not implement the writable `direction` property on 2D contexts, or the context was replaced by a mock in tests with non-writable properties.","commonSituations":"Non-standard embedding runtimes (Node-based wasm testing with canvas mocks), browser versions lacking full CanvasRenderingContext2D.direction support, or test double objects whose property descriptors are non-writable.","solutions":["Run in an up-to-date browser with full CanvasRenderingContext2D.direction support","If using a canvas mock/shim in tests, define properties as writable or implement a setter that returns true","Check for proxies intercepting the context object and allow-list the 'direction' property","Fall back to not setting direction (accepting default) if the environment cannot support it"],"exampleFix":"// before\nensure!(assigned, \"Canvas text direction could not be set\");\n// after\nif !assigned {\n    log::warn!(\"Canvas text direction could not be set; relying on default direction\");\n}\nOk(())","handlingStrategy":"try-catch","validationCode":"// probe whether the context accepts property writes before configuring\nlet probe = js_sys::Reflect::set(\n    context.as_ref(),\n    &JsValue::from_str(\"direction\"),\n    &JsValue::from_str(\"ltr\"),\n).unwrap_or(false);\nif !probe { log::warn!(\"context rejects direction writes; metrics may vary\"); }","typeGuard":"fn context_accepts_writes(context: &js_sys::Object) -> bool {\n    !js_sys::Object::is_frozen(context) && !js_sys::Object::is_sealed(context)\n}","tryCatchPattern":"match canvas.configure(&css_font) {\n    Err(e) if e.to_string().contains(\"direction could not be set\") => {\n        // proceed with default direction; log for diagnostics\n        log::warn!(\"direction ltr unsupported: {e}\");\n    }\n    Err(e) => return Err(e),\n    Ok(()) => (),\n}","preventionTips":["Keep canvas context objects un-frozen and un-sealed throughout their lifetime","Use current browser versions; 'direction' support on 2D contexts is broad but not universal","Avoid wrapping the context in JS proxies in test shims","Treat direction assignment as best-effort and degrade gracefully rather than failing hard where text direction is not critical"],"tags":["canvas","wasm","javascript","text-rendering"],"backgroundTag":"internal-invariant-violation","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"}