iced-rs/iced · error
lock font name cache
Error message
lock font name cache
What it means
`font::Family::name` interns font family names forever in a global `Mutex<FxHashSet<&'static str>>`. The `.expect("lock font name cache")` panics only when that mutex is poisoned, i.e. some earlier thread panicked while holding the lock inside `Family::name`. This panic is therefore always a cascade of an earlier, different panic.
Source
Thrown at core/src/font.rs:124
/// A list of all the different standalone family variants.
pub const VARIANTS: &[Self] = &[
Self::Serif,
Self::SansSerif,
Self::Cursive,
Self::Fantasy,
Self::Monospace,
];
/// Creates a [`Family::Name`] from the given string.
///
/// The name is interned in a global cache and never freed.
pub fn name(name: &str) -> Self {
use rustc_hash::FxHashSet;
use std::sync::{LazyLock, Mutex};
static NAMES: LazyLock<Mutex<FxHashSet<&'static str>>> = LazyLock::new(Mutex::default);
let mut names = NAMES.lock().expect("lock font name cache");
let Some(name) = names.get(name) else {
let name: &'static str = name.to_owned().leak();
let _ = names.insert(name);
return Self::Name(name);
};
Self::Name(name)
}
}
impl From<&str> for Family {
fn from(name: &str) -> Self {
Family::name(name)
}
}
View on GitHub (pinned to 2cffa99b39)
Solutions
- Find and fix the ORIGINAL panic (look earlier in the logs — poisoning is always secondary)
- As a maintainer, recover instead of panicking: `NAMES.lock().unwrap_or_else(PoisonError::into_inner)`
- Replace the interner lock with parking_lot::Mutex, which does not poison
- Resolve family names once at startup on a single thread to shrink the race window
Example fix
// before
let mut names = NAMES.lock().expect("lock font name cache");
// after
let mut names = NAMES
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner); Defensive patterns
Strategy: fallback
Try / catch
// maintainer-side: never let interning panic on poisoned state
let mut names = NAMES
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner); // data is still valid Prevention
- Fix the FIRST panic in a process — lock poisoning always has an earlier root cause
- Resolve font family names once at startup on one thread instead of lazily from many threads
- If you wrap iced in catch_unwind crash reporting, exit or rebuild state after a panic instead of continuing
- Prefer locking primitives without poisoning (parking_lot) in your own globals that mirror this pattern
When it happens
Trigger: Any call to `Family::name("...")` — styling text with a named family, `Compositor::list_fonts`, or font-loading flows — executed after a previous panic left the NAMES mutex poisoned. The poison source is a panic in the brief critical section (interning/allocating the leaked name) on another thread.
Common situations: A panicking worker thread that happened to be interning a family name while a crash reporter swallowed the original panic; heavy multithreaded font loading at startup; any catch_unwind-based harness that keeps running after a first panic and later touches fonts.
Related errors
- Lock hot functions
- Write to font system
- Read from font system
- Write application metadata
- Read last palette
AI-assisted analysis of iced-rs/iced@2cffa99b39 (2026-08-16).
Data as JSON: /api/errors/f7329ca4f0d563fe.
Report an issue: GitHub.