{"record":{"id":"273ada992db05326","repo":"iced-rs/iced","slug":"write-to-font-system","errorCode":null,"errorMessage":"Write to font system","messagePattern":"Write to font system","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphics/src/compositor.rs","lineNumber":57,"sourceCode":"        &mut self,\n        window: impl Window + Clone,\n        width: u32,\n        height: u32,\n    ) -> Self::Surface;\n\n    /// Configures a new [`Surface`] with the given dimensions.\n    ///\n    /// [`Surface`]: Self::Surface\n    fn configure_surface(&mut self, surface: &mut Self::Surface, width: u32, height: u32);\n\n    /// Returns [`Information`] used by this [`Compositor`].\n    fn information(&self) -> Information;\n\n    /// Loads a font from its bytes.\n    fn load_font(&mut self, font: Cow<'static, [u8]>) -> Result<(), font::Error> {\n        crate::text::font_system()\n            .write()\n            .expect(\"Write to font system\")\n            .load_font(font);\n\n        // TODO: Error handling\n        Ok(())\n    }\n\n    /// Lists all the available font families.\n    fn list_fonts(&mut self) -> Result<Vec<font::Family>, font::Error> {\n        use std::collections::BTreeSet;\n\n        let font_system = crate::text::font_system()\n            .read()\n            .expect(\"Read from font system\");\n\n        let families = BTreeSet::from_iter(font_system.families());\n\n        Ok(families.into_iter().map(font::Family::name).collect())\n    }","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/iced-rs/iced/blob/2cffa99b395d84fe469b44dccb56bbacd2f1a157/graphics/src/compositor.rs#L39-L75","documentation":"`Compositor::load_font` hands custom font bytes to the global cosmic-text `font_system()` behind an `RwLock`; `.write().expect(\"Write to font system\")` panics when that lock is poisoned by an earlier panic during text layout/shaping on another thread. Acquiring the write lock re-entrantly while a read guard is alive on the same thread would deadlock instead.","triggerScenarios":"Loading application fonts (the fonts() list / load_font) after any thread panicked mid-layout while holding the font-system lock; loading fonts lazily from multiple threads once rendering has started.","commonSituations":"A panic inside a text-rendering worker (malformed font data, cosmic-text edge case) poisons the global, and the next frame or font load kills the app; custom fonts loaded late in the lifecycle instead of before the first draw.","solutions":["Find the original panic in the text pipeline — this expect is secondary poisoning","Load all custom fonts at startup, before spawning render/layout work","Recover from poison instead of panicking: `write().unwrap_or_else(PoisonError::into_inner)`","Validate font bytes before handing them to load_font so bad data fails early and cleanly"],"exampleFix":"// before\ncrate::text::font_system().write().expect(\"Write to font system\").load_font(font);\n// after\ncrate::text::font_system()\n    .write()\n    .unwrap_or_else(std::sync::PoisonError::into_inner)\n    .load_font(font);","handlingStrategy":"validation","validationCode":"fn looks_like_font(bytes: &[u8]) -> bool {\n    if bytes.len() < 4 {\n        return false;\n    }\n    matches!(&bytes[..4], b\"OTTO\" | b\"ttcf\" | b\"true\" | b\"wOFF\")\n        || bytes.starts_with(&[0x00, 0x01, 0x00, 0x00]) // TrueType\n}\n\nif !looks_like_font(&font_bytes) {\n    return Err(font::Error::InvalidFont); // fail before touching the global font system\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Load all custom fonts at startup, before any thread can hold the font-system lock","Validate font bytes (magic/version) before passing them to load_font so bad data fails cleanly","A panic here is always downstream of an earlier text-pipeline panic — find that one first","Keep font loading single-threaded; the global cosmic-text state makes concurrency fragile"],"tags":["rust","iced","graphics","font","cosmic-text","rwlock","lock-poisoning","panic"],"backgroundTag":"lock-poisoned","analyzedSha":"2cffa99b395d84fe469b44dccb56bbacd2f1a157","analyzedAt":"2026-08-16T19:41:49.083Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}