{"record":{"id":"ae1b3a6bf866bc16","repo":"niri-wm/niri","slug":"unsupported-shm-format-format","errorCode":null,"errorMessage":"unsupported shm format: {format:?}","messagePattern":"unsupported shm format: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/render_helpers/mod.rs","lineNumber":345,"sourceCode":"}\n\npub fn render_to_shm(\n    renderer: &mut GlesRenderer,\n    damage_tracker: &mut OutputDamageTracker,\n    buffer: &WlBuffer,\n    format: wl_shm::Format,\n    elements: &[impl RenderElement<GlesRenderer>],\n    states: RenderElementStates,\n) -> anyhow::Result<()> {\n    let _span = tracy_client::span!();\n    // The pointer and length are the client's entire pool, which may hold other\n    // buffers besides this one... buffer_data is the one we want.\n    shm::with_buffer_contents_mut(buffer, |pool, pool_len, buffer_data| {\n        let (size, _scale, _transform) = damage_tracker.mode().try_into().unwrap();\n        let fourcc = match format {\n            wl_shm::Format::Xrgb8888 => Fourcc::Xrgb8888,\n            wl_shm::Format::Argb8888 => Fourcc::Argb8888,\n            _ => bail!(\"unsupported shm format: {format:?}\"),\n        };\n\n        ensure!(\n            // The buffer prefers pixels in little endian ...\n            buffer_data.format == format\n                && buffer_data.width == size.w\n                && buffer_data.height == size.h,\n            \"invalid buffer format or size\"\n        );\n\n        // The client chooses the stride and may pad rows, so only the first\n        // row_len bytes can be used here.\n        let row_len = size.w as usize * 4;\n        let height = size.h as usize;\n        let offset = usize::try_from(buffer_data.offset).context(\"negative buffer offset\")?;\n        let stride = usize::try_from(buffer_data.stride).context(\"negative buffer stride\")?;\n\n        // This should have already been validated by wl_shm, and a pool can","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/niri-wm/niri/blob/62c230a662ac913a54fc49c86fda0406da3f3ba9/src/render_helpers/mod.rs#L327-L363","documentation":"render_to_shm only accepts wl_shm buffers whose pixel format is Xrgb8888 or Argb8888; any other wl_shm::Format (e.g. Xbgr8888, RGB565, or 10-bit formats) hits the catch-all arm and bails. The conversion to a smithay Fourcc simply has no mapping for other formats, so rendering into that SHM buffer is refused early.","triggerScenarios":"Calling render_for_image_copy_capture, render_for_image_copy_cursor_capture, or render_for_screencopy_internal with a target wl_shm buffer whose shm::Format is not Xrgb8888/Argb8888 — e.g. a client or capture pipeline negotiating a different shm format.","commonSituations":"Screencast/capture clients negotiating non-8-bit or non-BGRA shm formats; copy-pasted buffer allocation code using a different wl_shm::Format; protocol peers advertising formats the renderer never intended to support.","solutions":["Reallocate or request the target buffer with wl_shm::Format::Xrgb8888 or Argb8888 before calling render_to_shm","If you control buffer negotiation, restrict the advertised shm formats to those two","Add a Fourcc mapping for the needed format in the match and confirm the byte layout matches the little-endian assumption"],"exampleFix":"// before\nlet attrs = BufferAllocation { format: wl_shm::Format::Xbgr8888, .. };\n// after\nlet attrs = BufferAllocation { format: wl_shm::Format::Argb8888, .. };","handlingStrategy":"validation","validationCode":"if !matches!(format, wl_shm::Format::Xrgb8888 | wl_shm::Format::Argb8888) {\n    return Err(anyhow!(\"capture buffer must be Xrgb8888/Argb8888, got {format:?}\"));\n}","typeGuard":"fn is_supported_shm_format(f: wl_shm::Format) -> bool {\n    matches!(f, wl_shm::Format::Xrgb8888 | wl_shm::Format::Argb8888)\n}","tryCatchPattern":"match render_for_image_copy_capture(...) {\n    Err(e) if e.to_string().contains(\"unsupported shm format\") => {\n        // reallocate buffer as Argb8888 and retry once\n    }\n    other => other?,\n}","preventionTips":["Restrict advertised shm formats to Xrgb8888/Argb8888 in any format negotiation","Allocate capture buffers via a helper that hardcodes the supported format","Assert the buffer format before each render call in debug builds"],"tags":["shm","screencopy","pixel-format"],"backgroundTag":"unsupported-enum-value","analyzedSha":"62c230a662ac913a54fc49c86fda0406da3f3ba9","analyzedAt":"2026-09-19T19:48:44.526Z","contentChangedAt":"2026-09-19T19:48:44.526Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}