{"record":{"id":"3ecf9238b11a82b5","repo":"flxzt/rnote","slug":"creating-rgbaimage-from-data-failed-for-image-with","errorCode":null,"errorMessage":"Creating RgbaImage from data failed for image with memory-format {:?}.","messagePattern":"Creating RgbaImage from data failed for image with memory-format (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/image.rs","lineNumber":233,"sourceCode":"            pixel_height: height,\n            // cairo renders to bgra8-premultiplied, but we convert it to rgba8-premultiplied\n            memory_format: ImageMemoryFormat::R8g8b8a8Premultiplied,\n        })\n    }\n\n    pub fn into_imgbuf(\n        self,\n    ) -> Result<image::ImageBuffer<image::Rgba<u8>, Vec<u8>>, anyhow::Error> {\n        self.assert_valid()?;\n\n        match self.memory_format {\n            ImageMemoryFormat::R8g8b8a8Premultiplied => image::RgbaImage::from_vec(\n                self.pixel_width,\n                self.pixel_height,\n                self.data.to_vec(),\n            )\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"Creating RgbaImage from data failed for image with memory-format {:?}.\",\n                    self.memory_format\n                )\n            }),\n        }\n    }\n\n    /// Encodes the image into the provided format.\n    ///\n    /// When the format is `Jpeg`, the quality should be provided, but falls back to 93 if it is None.\n    pub fn into_encoded_bytes(\n        self,\n        format: image::ImageFormat,\n        quality: Option<u8>,\n    ) -> Result<Vec<u8>, anyhow::Error> {\n        const QUALITY_FALLBACK: u8 = 93;\n\n        self.assert_valid()?;","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/image.rs#L215-L251","documentation":"image::RgbaImage::from_vec returned None when wrapping the image's raw bytes into an RGBA buffer, meaning the byte vector length does not exactly match width*height*4 for the given memory format. Raised inside into_imgbuf after assert_valid's format handling.","triggerScenarios":"Calling into_imgbuf (directly or via into_encoded_bytes) on an Image whose data buffer size disagrees with pixel_width*pixel_height*4, bypassing or racing the earlier assert.","commonSituations":"Images constructed from GdkTexture bytes with unaligned row stride; data mutated after construction; images saved/loaded with dimension metadata mismatch.","solutions":["Ensure data.len() == pixel_width*pixel_height*4 before constructing the Image (see assert_valid).","If the texture has a row stride larger than width*4, strip padding row by row instead of using the raw bytes.","Re-encode the image to RGBA8 with no padding upstream.","Check the memory_format field matches the actual layout of data (premultiplied vs straight)."],"exampleFix":"// before\nlet img = image.into_imgbuf()?;\n// after\nlet image = image.crop_to_exact_stride(); // removes row padding\nlet img = image.into_imgbuf()?;","handlingStrategy":"validation","validationCode":"// rust\nfn exact_rgba8_size(w: u32, h: u32, data: &[u8]) -> bool {\n    (w as usize) * (h as usize) * 4 == data.len()\n}","typeGuard":"fn has_no_row_padding(stride: usize, width: u32) -> bool {\n    stride == width as usize * 4\n}","tryCatchPattern":"let imgbuf = match image.into_imgbuf() {\n    Ok(b) => b,\n    Err(e) => { log::error!(\"{e}\"); return Err(anyhow!(\"image buffer conversion failed\")); }\n};","preventionTips":["Strip row stride padding from GdkTexture bytes before constructing Image.","Keep memory_format in sync with the actual byte layout.","Run assert_valid before buffer conversion."],"tags":["image","buffer-size","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}