{"record":{"id":"24cec67f3e7297ce","repo":"iced-rs/iced","slug":"read-text-atlas","errorCode":null,"errorMessage":"Read text atlas","messagePattern":"Read text atlas","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"wgpu/src/text.rs","lineNumber":394,"sourceCode":"                        cache,\n                        layer_transformation * *transformation,\n                        layer_bounds * layer_transformation,\n                    );\n                }\n            }\n        }\n    }\n\n    pub fn render<'a>(\n        &'a self,\n        pipeline: &'a Pipeline,\n        viewport: &'a Viewport,\n        start: usize,\n        batch: &'a Batch,\n        bounds: Rectangle<u32>,\n        render_pass: &mut wgpu::RenderPass<'a>,\n    ) -> usize {\n        let atlas = pipeline.atlas.read().expect(\"Read text atlas\");\n        let mut layer_count = 0;\n\n        render_pass.set_scissor_rect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n        for item in batch {\n            match item {\n                Item::Group { .. } => {\n                    let renderer = &self.renderers[start + layer_count];\n\n                    renderer\n                        .render(&atlas, &viewport.0, render_pass)\n                        .expect(\"Render text\");\n\n                    layer_count += 1;\n                }\n                Item::Cached { cache, .. } => {\n                    if let Some((atlas, upload)) = self.storage.get(cache) {\n                        upload","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/iced-rs/iced/blob/3de451447bd28217bb535632867550908e29d5d0/wgpu/src/text.rs#L376-L412","documentation":"State::render takes the read lock on the shared cryoglyph TextAtlas to bind glyph textures for drawing text layers. As with every std RwLock, read() errs only when the lock is poisoned by a panic that unwound while a writer held it; this panic is the read-side symptom of an earlier failure in text preparation.","triggerScenarios":"Any frame rendered after a panic inside State::prepare (or Pipeline::trim) unwound through the atlas write guard; the very next render that contains text then aborts here with \"Read text atlas\".","commonSituations":"Post-crash rendering attempts in long-lived processes; multi-window apps where the poisoned atlas is shared through the cloned Pipeline; CI screenshot pipelines that continue after swallowing a first panic.","solutions":["Diagnose and fix the original panic (search above this frame in the backtrace)","Restart the process if the poison already happened; the lock never un-poisons itself","In a patched iced, replace the expect with unwrap_or_else(|poisoned| poisoned.into_inner()) to render with possibly stale atlas data"],"exampleFix":"// before (iced internals)\nlet atlas = pipeline.atlas.read().expect(\"Read text atlas\");\n\n// after\nlet atlas = pipeline\n    .atlas\n    .read()\n    .unwrap_or_else(|poisoned| poisoned.into_inner());","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Recovery pattern for a poisoned atlas read lock (patched iced or your own locks):\nlet atlas = match pipeline.atlas.read() {\n    Ok(guard) => guard,\n    Err(poisoned) => poisoned.into_inner(), // draw with last-known-good atlas contents\n};","preventionTips":["Once poisoned, the lock stays poisoned: restart the process rather than expecting self-healing","Root-cause the prepare-side panic that poisoned the atlas; this read is only the symptom","Capture full backtraces (RUST_BACKTRACE=1) so the original poisoning frame is identifiable"],"tags":["wgpu","text-rendering","rwlock","poisoned-lock","font-atlas","rust"],"backgroundTag":"rwlock-poisoned","analyzedSha":"3de451447bd28217bb535632867550908e29d5d0","analyzedAt":"2026-08-17T10:40:26.997Z","contentChangedAt":"2026-08-17T10:40:26.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}