{"record":{"id":"c995ce2e29ff6ca5","repo":"iced-rs/iced","slug":"write-font-system","errorCode":null,"errorMessage":"Write font system","messagePattern":"Write font system","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphics/src/text/editor.rs","lineNumber":313,"sourceCode":"\n        let selection = match editor.selection() {\n            cosmic_text::Selection::None => None,\n            cosmic_text::Selection::Normal(cursor)\n            | cosmic_text::Selection::Line(cursor)\n            | cosmic_text::Selection::Word(cursor) => Some(Position {\n                line: cursor.line,\n                index: cursor.index,\n            }),\n        };\n\n        Cursor {\n            position,\n            selection,\n        }\n    }\n\n    fn perform(&mut self, action: Action) {\n        let mut font_system = text::font_system().write().expect(\"Write font system\");\n\n        self.with_internal_mut(|internal| {\n            let editor = &mut internal.editor;\n\n            match action {\n                // Motion events\n                Action::Move(motion) => {\n                    if let Some((start, end)) = editor.selection_bounds() {\n                        editor.set_selection(cosmic_text::Selection::None);\n\n                        match motion {\n                            // These motions are performed as-is even when a selection\n                            // is present\n                            Motion::Home\n                            | Motion::End\n                            | Motion::DocumentStart\n                            | Motion::DocumentEnd => {\n                                editor.action(","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/iced-rs/iced/blob/3de451447bd28217bb535632867550908e29d5d0/graphics/src/text/editor.rs#L295-L331","documentation":"iced keeps one global cosmic-text FontSystem behind a std::sync::RwLock (text::font_system() in graphics/src/text.rs:119). Every Editor mutation, including perform (editor.rs:313), takes the write lock with .write().expect(\"Write font system\"). That expect only fails when the lock is poisoned, i.e. some thread panicked earlier while holding this lock; this panic is fallout, and the root cause is the first panic inside a font-system critical section.","triggerScenarios":"An earlier panic while the font-system lock was held (a cosmic-text shaping panic, a panic in custom code running under the lock, or another iced text API that panicked), after which every Editor::perform dies with this message when it takes the lock.","commonSituations":"Background threads doing text work; apps that swallowed a first panic with catch_unwind and kept running; font loading problems (missing/malformed fonts) that panicked during shaping.","solutions":["Find and fix the FIRST panic: rerun with RUST_BACKTRACE=1; this expect's backtrace only shows the victim, so reproduce the earlier failure","If you drive text APIs on your own threads, wrap them in catch_unwind and shut down on Err instead of poisoning the global for the UI thread","Restart the process: a poisoned static RwLock cannot be unpoisoned in place","Upgrade iced: font-system and cosmic-text panics have been fixed across releases"],"exampleFix":"// before - background thread can poison the global font system\nstd::thread::spawn(|| { editor.perform(action); });\n\n// after - isolate panics so the global lock never gets poisoned\nlet ok = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    editor.perform(action)\n}));\nif ok.is_err() {\n    std::process::abort(); // fail fast instead of poisoning every later text call\n}","handlingStrategy":"validation","validationCode":"// with a direct iced_graphics dependency\nif iced_graphics::text::font_system().is_poisoned() {\n    // an earlier panic poisoned the global: fail fast with a clear message\n    return Err(\"font system poisoned by an earlier panic\".into());\n}","typeGuard":null,"tryCatchPattern":"let ok = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    editor.perform(action)\n}));\nif ok.is_err() {\n    // do not keep running: every later text call will hit the poisoned lock\n    std::process::abort();\n}","preventionTips":["Fix the FIRST panic; run with RUST_BACKTRACE=1 and inspect the earliest failure","Never swallow panics from text APIs and keep the app running","Wrap background text work in catch_unwind and treat Err as fatal","Keep text usage on the UI thread unless you isolate worker panics"],"tags":["rust","iced","rwlock","poisoned-lock","font-system","cosmic-text","editor"],"backgroundTag":"rwlock-poisoned","analyzedSha":"3de451447bd28217bb535632867550908e29d5d0","analyzedAt":"2026-08-17T10:40:26.997Z","contentChangedAt":"2026-08-17T10:40:26.997Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}