{"record":{"id":"b7742e41e0694e18","repo":"iced-rs/iced","slug":"write-to-text-atlas","errorCode":null,"errorMessage":"Write to text atlas","messagePattern":"Write to text atlas","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"wgpu/src/text.rs","lineNumber":323,"sourceCode":"}\n\nimpl State {\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    pub fn prepare(\n        &mut self,\n        pipeline: &Pipeline,\n        device: &wgpu::Device,\n        queue: &wgpu::Queue,\n        viewport: &Viewport,\n        encoder: &mut wgpu::CommandEncoder,\n        batch: &Batch,\n        layer_bounds: Rectangle,\n        layer_transformation: Transformation,\n    ) {\n        let mut atlas = pipeline.atlas.write().expect(\"Write to text atlas\");\n\n        for item in batch {\n            match item {\n                Item::Group {\n                    transformation,\n                    text,\n                } => {\n                    if self.renderers.len() <= self.prepare_layer {\n                        self.renderers.push(cryoglyph::TextRenderer::new(\n                            &mut atlas,\n                            device,\n                            wgpu::MultisampleState::default(),\n                            None,\n                        ));\n                    }\n\n                    let renderer = &mut self.renderers[self.prepare_layer];\n                    let result = prepare(","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/iced-rs/iced/blob/3de451447bd28217bb535632867550908e29d5d0/wgpu/src/text.rs#L305-L341","documentation":"State::prepare acquires the write lock on the shared text atlas before laying out and rasterizing each text batch with cryoglyph (iced's glyphon fork). The expect on pipeline.atlas.write() panics when the lock is already poisoned by an earlier panic that unwound while holding it, including panics from the nested font_system().write() lock taken inside the same function.","triggerScenarios":"A previous frame's text preparation panicked (font parsing failure, unwrap on malformed shaped text, a user callback in the text pipeline) while holding the atlas write guard; every subsequent frame then aborts at this line. In multi-window apps any window sharing the Pipeline can be the poisoner.","commonSituations":"Dynamic font loading of corrupt files; edge-case glyphs (rare scripts, color emoji) hitting rasterizer panics; one poisoned window cascading to all windows of the process.","solutions":["Fix the first text-related panic in the log; this expect is downstream damage","Pre-load and validate fonts at startup instead of lazily during prepare","Reproduce with debug symbols to identify whether the poisoner is the atlas or font-system lock and report to iced"],"exampleFix":"// before (iced internals)\nlet mut atlas = pipeline.atlas.write().expect(\"Write to text atlas\");\n\n// after\nlet mut atlas = pipeline\n    .atlas\n    .write()\n    .unwrap_or_else(|poisoned| poisoned.into_inner());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// If you embed iced and cannot guarantee panic-free text pipelines,\n// fence the frame so a panic never unwinds through the atlas lock twice:\nmatch std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    compositor.present(&mut renderer, &mut surface, &viewport, background, || {})\n})) {\n    Ok(result) => result?,\n    Err(payload) => {\n        log::error!(\"frame panicked: {payload:?}; recreating window state\");\n        // rebuild compositor/surface state instead of reusing poisoned locks\n    }\n}","preventionTips":["Validate custom font bytes before handing them to the font system","In multi-window apps, isolate windows so one poisoned pipeline does not take down every window sharing the Engine"],"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"}