{"record":{"id":"95cc37518d27e414","repo":"iced-rs/iced","slug":"read-primitive-storage","errorCode":null,"errorMessage":"Read primitive storage","messagePattern":"Read primitive storage","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"wgpu/src/lib.rs","lineNumber":515,"sourceCode":"                                load: wgpu::LoadOp::Load,\n                                store: wgpu::StoreOp::Store,\n                            },\n                        })],\n                        depth_stencil_attachment: None,\n                        timestamp_writes: None,\n                        occlusion_query_set: None,\n                        multiview_mask: None,\n                    }));\n            }\n\n            if !layer.primitives.is_empty() {\n                let render_span = debug::render(debug::Primitive::Shader);\n\n                let primitive_storage = self\n                    .engine\n                    .primitive_storage\n                    .read()\n                    .expect(\"Read primitive storage\");\n\n                let mut need_render = Vec::new();\n\n                for instance in &layer.primitives {\n                    let bounds = instance.bounds * scale;\n\n                    if let Some(clip_bounds) = (instance.bounds * scale)\n                        .intersection(&physical_bounds)\n                        .and_then(Rectangle::snap)\n                    {\n                        render_pass.set_viewport(\n                            bounds.x,\n                            bounds.y,\n                            bounds.width,\n                            bounds.height,\n                            0.0,\n                            1.0,\n                        );","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/iced-rs/iced/blob/a8ff2d522552c1252b88afc02bc310dd657cd25e/wgpu/src/lib.rs#L497-L533","documentation":"On the render side of present(), iced takes the read lock on primitive::Storage to issue draw calls for prepared primitives. RwLock::read returns Err only on poisoning, so this panic means a writer panicked earlier while holding the lock (commonly a failing Primitive::prepare on this or another window sharing the Engine).","triggerScenarios":"Any frame following a panic that unwound through primitive_storage.write() in the prepare phase; multi-window applications where window A's prepare panicked and window B's render is the first subsequent lock acquisition.","commonSituations":"Crash cascades in multi-window desktop apps; embedding a iced viewport inside a host that catches the first panic and keeps running; devtools windows sharing the engine with the main window.","solutions":["Fix the first panic in the log (the poisoner); later lock errors disappear with it","Keep prepare()/draw() code of custom primitives panic-free","Recover instead of crashing by using unwrap_or_else(|p| p.into_inner()) in a patched iced build"],"exampleFix":"// before (iced internals)\nlet primitive_storage = self.engine.primitive_storage.read().expect(\"Read primitive storage\");\n\n// after\nlet primitive_storage = self\n    .engine\n    .primitive_storage\n    .read()\n    .unwrap_or_else(|poisoned| poisoned.into_inner());","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Recovery pattern for a poisoned read lock (your own RwLocks or patched iced):\nlet storage = match engine.primitive_storage.read() {\n    Ok(guard) => guard,\n    Err(poisoned) => poisoned.into_inner(), // data may be stale but consistent enough to draw\n};","preventionTips":["Fix the poisoning writer, not this reader: the first panic in the log is the actionable bug","Keep custom primitive prepare panic-free so read-side locks never see poison","Avoid catch_unwind around the whole event loop that swallows the first panic and turns it into recurring poison panics"],"tags":["wgpu","rwlock","poisoned-lock","render-loop","rust"],"backgroundTag":"rwlock-poisoned","analyzedSha":"a8ff2d522552c1252b88afc02bc310dd657cd25e","analyzedAt":"2026-08-17T10:40:26.997Z","contentChangedAt":"2026-08-17T10:40:26.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}