iced-rs/iced · error
Write font system
Error message
Write font system
What it means
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.
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
Example fix
// before - background thread can poison the global font system
std::thread::spawn(|| { editor.perform(action); });
// after - isolate panics so the global lock never gets poisoned
let ok = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
editor.perform(action)
}));
if ok.is_err() {
std::process::abort(); // fail fast instead of poisoning every later text call
} Defensive patterns
Strategy: validation
Validate before calling
// with a direct iced_graphics dependency
if iced_graphics::text::font_system().is_poisoned() {
// an earlier panic poisoned the global: fail fast with a clear message
return Err("font system poisoned by an earlier panic".into());
} Try / catch
let ok = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
editor.perform(action)
}));
if ok.is_err() {
// do not keep running: every later text call will hit the poisoned lock
std::process::abort();
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Read font system
- Write font system
- Line layout should be cached
- Editor cannot have multiple strong references
- Editor should always be initialized
AI-assisted analysis of iced-rs/iced@3de451447b (2026-08-17).
Data as JSON: /api/errors/c995ce2e29ff6ca5.
Report an issue: GitHub.
Appendix: source
Thrown at graphics/src/text/editor.rs:313
let selection = match editor.selection() {
cosmic_text::Selection::None => None,
cosmic_text::Selection::Normal(cursor)
| cosmic_text::Selection::Line(cursor)
| cosmic_text::Selection::Word(cursor) => Some(Position {
line: cursor.line,
index: cursor.index,
}),
};
Cursor {
position,
selection,
}
}
fn perform(&mut self, action: Action) {
let mut font_system = text::font_system().write().expect("Write font system");
self.with_internal_mut(|internal| {
let editor = &mut internal.editor;
match action {
// Motion events
Action::Move(motion) => {
if let Some((start, end)) = editor.selection_bounds() {
editor.set_selection(cosmic_text::Selection::None);
match motion {
// These motions are performed as-is even when a selection
// is present
Motion::Home
| Motion::End
| Motion::DocumentStart
| Motion::DocumentEnd => {
editor.action(View on GitHub (pinned to 3de451447b)