iced-rs/iced · error

Write text atlas

Error message

Write text atlas

What it means

The text pipeline keeps its cryoglyph TextAtlas behind an Arc<RwLock> shared by all renderers; Pipeline::trim acquires the write lock to evict unused glyphs. The expect fires when that lock is poisoned, i.e. a panic previously unwound while holding the atlas write lock inside State::prepare (glyph rasterization, layout, or the also-lock-protected font system).

Source

Thrown at wgpu/src/text.rs:295

impl Pipeline {
    pub fn new(device: &wgpu::Device, queue: &wgpu::Queue, format: wgpu::TextureFormat) -> Self {
        let cache = cryoglyph::Cache::new(device);
        let atlas =
            cryoglyph::TextAtlas::with_color_mode(device, queue, &cache, format, COLOR_MODE);

        Pipeline {
            format,
            cache,
            atlas: Arc::new(RwLock::new(atlas)),
        }
    }

    pub fn create_viewport(&self, device: &wgpu::Device) -> Viewport {
        Viewport(cryoglyph::Viewport::new(device, &self.cache))
    }

    pub fn trim(&self) {
        self.atlas.write().expect("Write text atlas").trim();
    }
}

#[derive(Default)]
pub struct State {
    renderers: Vec<cryoglyph::TextRenderer>,
    prepare_layer: usize,
    cache: BufferCache,
    storage: Storage,
}

impl State {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn prepare(
        &mut self,

View on GitHub (pinned to 3de451447b)

Solutions

  1. Locate the original panic above this one in the crash trace and fix it (font loading or text layout)
  2. Ship valid default fonts and validate user-supplied font files before use
  3. Recover via unwrap_or_else(|poisoned| poisoned.into_inner()) in a patched iced if the process must survive

Example fix

// before (iced internals)
self.atlas.write().expect("Write text atlas").trim();

// after
self.atlas.write().unwrap_or_else(|poisoned| poisoned.into_inner()).trim();
Defensive patterns

Strategy: fallback

Try / catch

// Recovery pattern for a poisoned atlas lock (patched iced or your own locks):
let mut atlas = match pipeline.atlas.write() {
    Ok(guard) => guard,
    Err(poisoned) => {
        log::warn!("text atlas poisoned; recovering");
        poisoned.into_inner()
    }
};
atlas.trim();

Prevention

When it happens

Trigger: A panic during text preparation in an earlier frame (bad font data, a layout routine unwrapping on malformed content) poisoning the atlas lock; trim() then panics when the window is resized or widgets are dropped and cache trimming runs.

Common situations: Applications loading broken or missing fonts; long-lived apps that call renderer.trim() on memory pressure; a swallowed panic in an embedded runtime leaving the lock poisoned.

Related errors


AI-assisted analysis of iced-rs/iced@3de451447b (2026-08-17). Data as JSON: /api/errors/b67931c68815c5e3. Report an issue: GitHub.