{"record":{"id":"c59e49d50fa8bf2b","repo":"GraphiteEditor/Graphite","slug":"failed-to-convert-bytes-to-pixel","errorCode":null,"errorMessage":"Failed to convert bytes to pixel","messagePattern":"Failed to convert bytes to pixel","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"node-graph/libraries/no-std-types/src/color/color_traits.rs","lineNumber":97,"sourceCode":"pub trait Rec709Primaries {}\nimpl<T: Rec709Primaries> RGBPrimaries for T {\n\tconst RED: DVec2 = DVec2::new(0.64, 0.33);\n\tconst GREEN: DVec2 = DVec2::new(0.3, 0.6);\n\tconst BLUE: DVec2 = DVec2::new(0.15, 0.06);\n\tconst WHITE: DVec2 = DVec2::new(0.3127, 0.329);\n}\n\npub trait SRGB: Rec709Primaries {}\n\n// TODO: Come up with a better name for this trait\npub trait Pixel: Clone + Pod + Zeroable + Default {\n\t#[cfg(feature = \"std\")]\n\tfn to_bytes(&self) -> Vec<u8> {\n\t\tbytemuck::bytes_of(self).to_vec()\n\t}\n\t// TODO: use u8 for Color\n\tfn from_bytes(bytes: &[u8]) -> Self {\n\t\t*bytemuck::try_from_bytes(bytes).expect(\"Failed to convert bytes to pixel\")\n\t}\n\n\tfn byte_size() -> usize {\n\t\tsize_of::<Self>()\n\t}\n}\npub trait RGB: Pixel {\n\ttype ColorChannel: Channel;\n\n\tfn red(&self) -> Self::ColorChannel;\n\tfn r(&self) -> Self::ColorChannel {\n\t\tself.red()\n\t}\n\tfn green(&self) -> Self::ColorChannel;\n\tfn g(&self) -> Self::ColorChannel {\n\t\tself.green()\n\t}\n\tfn blue(&self) -> Self::ColorChannel;","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/node-graph/libraries/no-std-types/src/color/color_traits.rs#L79-L115","documentation":"Pixel::from_bytes converts a byte slice into a pixel value with bytemuck::try_from_bytes, which succeeds only when the slice length exactly equals size_of::<Self>() (with matching alignment). Any other length — a truncated buffer or a channel count different from the pixel type — fails the check and panics with this message.","triggerScenarios":"Feeding an RGBA (4-byte) buffer into an RGB pixel type or vice versa; slicing a buffer at a length that is not exactly the pixel size; empty slices produced by failed reads or zero-length image data.","commonSituations":"Converting between pixel layouts without re-interleaving channels; off-by-one stride handling when slicing image rows; deserialized buffers carrying wrong length fields.","solutions":["Assert bytes.len() == Self::byte_size() before calling from_bytes","Choose the Pixel type that matches the source's channel count and order (for example Rgba8 vs Rgb8)","For bulk buffers, iterate chunks_exact(byte_size()) and convert element by element"],"exampleFix":"// before\nlet pixel = P::from_bytes(bytes);\n\n// after\nassert_eq!(bytes.len(), P::byte_size(), \"pixel buffer must be exactly one pixel wide\");\nlet pixel = P::from_bytes(bytes);","handlingStrategy":"validation","validationCode":"fn is_pixel_sized<P: Pixel>(bytes: &[u8]) -> bool {\n\tbytes.len() == P::byte_size()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate buffer length against the pixel type before every from_bytes call","Match the pixel type to the source channel count and order exactly","Use chunks_exact over bulk buffers instead of ad-hoc slicing"],"tags":["bytemuck","pixel","image-data","byte-length"],"backgroundTag":"byte-length-mismatch","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}