iced-rs/iced · error
Read primitive storage
Error message
Read primitive storage
What it means
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).
Source
Thrown at wgpu/src/lib.rs:515
load: wgpu::LoadOp::Load,
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
multiview_mask: None,
}));
}
if !layer.primitives.is_empty() {
let render_span = debug::render(debug::Primitive::Shader);
let primitive_storage = self
.engine
.primitive_storage
.read()
.expect("Read primitive storage");
let mut need_render = Vec::new();
for instance in &layer.primitives {
let bounds = instance.bounds * scale;
if let Some(clip_bounds) = (instance.bounds * scale)
.intersection(&physical_bounds)
.and_then(Rectangle::snap)
{
render_pass.set_viewport(
bounds.x,
bounds.y,
bounds.width,
bounds.height,
0.0,
1.0,
);View on GitHub (pinned to a8ff2d5225)
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
Example fix
// before (iced internals)
let primitive_storage = self.engine.primitive_storage.read().expect("Read primitive storage");
// after
let primitive_storage = self
.engine
.primitive_storage
.read()
.unwrap_or_else(|poisoned| poisoned.into_inner()); Defensive patterns
Strategy: fallback
Try / catch
// Recovery pattern for a poisoned read lock (your own RwLocks or patched iced):
let storage = match engine.primitive_storage.read() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(), // data may be stale but consistent enough to draw
}; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- primitive storage should be writable
- Write text atlas
- Write to text atlas
- Read text atlas
- Write primitive storage
AI-assisted analysis of iced-rs/iced@a8ff2d5225 (2026-08-17).
Data as JSON: /api/errors/95cc37518d27e414.
Report an issue: GitHub.