{"record":{"id":"e4b4ed57ec894560","repo":"iced-rs/iced","slug":"create-pixel-map","errorCode":null,"errorMessage":"Create pixel map","messagePattern":"Create pixel map","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tiny_skia/src/window/compositor.rs","lineNumber":190,"sourceCode":"\n    if damage.is_empty() {\n        if let Some(last_frame) = last_frame {\n            surface.frames.push_front(last_frame.clone());\n        }\n    } else {\n        surface.frames.push_front(Frame {\n            background,\n            layers: renderer.layers().to_vec(),\n        });\n\n        let damage = damage::group(damage, Rectangle::with_size(viewport.logical_size()));\n\n        let mut pixels = tiny_skia::PixmapMut::from_bytes(\n            bytemuck::cast_slice_mut(&mut buffer),\n            physical_size.width,\n            physical_size.height,\n        )\n        .expect(\"Create pixel map\");\n\n        renderer.draw(\n            &mut pixels,\n            &mut surface.clip_mask,\n            viewport,\n            &damage,\n            background,\n        );\n    }\n\n    on_pre_present();\n    buffer.present().map_err(|_| compositor::SurfaceError::Lost)\n}\n\npub fn screenshot(\n    renderer: &mut Renderer,\n    viewport: &Viewport,\n    background_color: Color,","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/iced-rs/iced/blob/3de451447bd28217bb535632867550908e29d5d0/tiny_skia/src/window/compositor.rs#L172-L208","documentation":"Every frame, present() views the softbuffer backbuffer as a tiny_skia::PixmapMut via PixmapMut::from_bytes(buffer, width, height), which returns None when the byte length does not equal width*height*4. The buffer length is fixed by the last successful resize(), while physical_size comes from the current Viewport; any drift between the configured surface size and the viewport at present time breaks the invariant and this expect panics.","triggerScenarios":"A window resize or scale-factor change that lands between the runtime's configure_surface and the next present (surface_version bookkeeping missed an update); calling present() with a Viewport newer than the surface configuration; multi-window code presenting to a surface resized by another event path.","commonSituations":"Rapid interactive resizing; dragging a window between monitors with different scale factors; tiling window managers emitting resize bursts; custom runtimes that update the viewport but forget to reconfigure the surface.","solutions":["Ensure configure_surface runs for every physical-size or scale change before the next present (keep surface_version in sync like iced_winit does)","In a custom runtime, compare viewport.physical_size() with the size passed to the last resize() and reconfigure on mismatch before presenting","Patch iced to propagate the failure as compositor::SurfaceError::Lost instead of panicking so the runtime recreates the surface"],"exampleFix":"// before (iced internals)\nlet mut pixels = tiny_skia::PixmapMut::from_bytes(\n    bytemuck::cast_slice_mut(&mut buffer), physical_size.width, physical_size.height,\n).expect(\"Create pixel map\");\n\n// after\nlet mut pixels = tiny_skia::PixmapMut::from_bytes(\n    bytemuck::cast_slice_mut(&mut buffer), physical_size.width, physical_size.height,\n).ok_or(compositor::SurfaceError::Lost)?;","handlingStrategy":"validation","validationCode":"// In a custom runtime: reconfigure whenever the viewport drifts from the\n// size the softbuffer surface was last resized to.\nlet physical = viewport.physical_size();\nif physical != last_configured_size {\n    compositor.configure_surface(&mut surface, physical.width, physical.height);\n    last_configured_size = physical;\n}\ncompositor.present(&mut renderer, &mut surface, &viewport, background, || {})?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Handle every Resized and ScaleFactorChanged event by reconfiguring before the next redraw, like iced_winit's surface_version tracking does","Treat scale-factor changes as resizes: the physical buffer length changes even when the logical size does not"],"tags":["tiny-skia","pixmap","softbuffer","buffer-size-mismatch","window-resize","rust"],"backgroundTag":"buffer-size-mismatch","analyzedSha":"3de451447bd28217bb535632867550908e29d5d0","analyzedAt":"2026-08-17T10:40:26.997Z","contentChangedAt":"2026-08-17T10:40:26.997Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}