{"record":{"id":"f14a2fe6d45e1719","repo":"bevyengine/bevy","slug":"invalid-array-layout-0","errorCode":null,"errorMessage":"Invalid array layout: {0}","messagePattern":"Invalid array layout: (.+?)","errorType":"exception","errorClass":"ImageLoaderError","httpStatus":null,"severity":"error","filePath":"crates/bevy_image/src/image_loader.rs","lineNumber":185,"sourceCode":"            sampler: ImageSampler::Default,\n            asset_usage: RenderAssetUsages::default(),\n            array_layout: None,\n        }\n    }\n}\n\n/// An error when loading an image using [`ImageLoader`].\n#[non_exhaustive]\n#[derive(Debug, Error)]\npub enum ImageLoaderError {\n    /// An error occurred while trying to load the image bytes.\n    #[error(\"Failed to load image bytes: {0}\")]\n    Io(#[from] std::io::Error),\n    /// An error occurred while trying to decode the image bytes.\n    #[error(\"Could not load texture file: {0}\")]\n    FileTexture(#[from] FileTextureError),\n    /// An error occurred while trying to interpret the image bytes as an array texture.\n    #[error(\"Invalid array layout: {0}\")]\n    ArrayLayout(#[from] TextureReinterpretationError),\n}\n\nimpl AssetLoader for ImageLoader {\n    type Asset = Image;\n    type Settings = ImageLoaderSettings;\n    type Error = ImageLoaderError;\n    async fn load(\n        &self,\n        reader: &mut dyn Reader,\n        settings: &ImageLoaderSettings,\n        load_context: &mut LoadContext<'_>,\n    ) -> Result<Image, Self::Error> {\n        let mut bytes = Vec::new();\n        reader.read_to_end(&mut bytes).await?;\n        let image_type = match settings.format {\n            ImageFormatSetting::FromExtension => {\n                // use the file extension for the image type","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_image/src/image_loader.rs#L167-L203","documentation":"ImageLoaderError::ArrayLayout (image_loader.rs:185-186) wraps TextureReinterpretationError, raised when ImageLoaderSettings::array_layout reinterprets a stacked 2D image as a texture array (image_loader.rs:245-265). The inner variants (image.rs:2200-2246) name the exact problem: WrongDimension (not a 2D image), InvalidLayerCount (already layered), HeightNotDivisibleByLayers, GridHeightNotDivisibleByTileHeight/GridWidthNotDivisibleByTileWidth, NotEnoughLayers, IncompatibleSizes, and InvalidTextureFormat (\"Is it compressed?\"). It fires after a successful decode, while slicing the pixel data into layers.","triggerScenarios":"Setting array_layout in an image's .meta or via load_with_settings: RowCount { rows } on a sheet whose height is not divisible by rows; RowHeight/GridCount on a grid that does not tile evenly (image_loader.rs:248-264); an already-layered or 3D source; a compressed source format (InvalidTextureFormat).","commonSituations":"Texture2DArray sprite sheets authored with off-by-one pixel sizes (e.g. 256x252 for 4 rows of 64); grid layouts declared with swapped columns/rows; applying array_layout meta to files that were already exported as arrays.","solutions":["Make the sheet geometry exact: height must be rows * row_height and the grid must divide evenly into tiles (verify width % tile_w == 0 and height % tile_h == 0).","Double-check the RowCount/RowHeight/GridCount/GridSize settings — swapped rows/columns is the most common mistake.","Ensure the source image is a plain single-layer 2D uncompressed image (PNG), not an already-layered or compressed file.","For RowHeight/GridSize, remember Bevy divides image.height() by the value you give — pick the number that yields an integer layer count >= 2 (NotEnoughLayers otherwise)."],"exampleFix":"// before — sheet is 256x252, rows = 4 (252 is not divisible)\n// textures/particles.meta: \"loader\": { \"settings\": { \"array_layout\": { \"type\": \"row_count\", \"rows\": 4 } } }\n\n// after — author the sheet at an exact multiple (4 * 64 = 256) and keep the same meta\n// re-export particles.png at 256x256","handlingStrategy":"validation","validationCode":"// verify the sheet divides evenly before enabling array_layout\nlet (w, h) = (image.width(), image.height());\nlet layers = h / row_height;\nassert!(h % row_height == 0 && layers >= 2, \"height {h} not divisible by {row_height}\");\nassert!(w % tile_w == 0 && h % tile_h == 0, \"grid must divide evenly\");","typeGuard":"fn array_layout_ok(image: &Image, rows: u32) -> bool {\n    image.texture_descriptor.dimension == TextureDimension::D2\n        && image.texture_descriptor.size.depth_or_array_layers == 1\n        && image.height() % rows == 0\n        && image.height() / rows >= 2\n        && !image.is_compressed()\n}","tryCatchPattern":"// array_layout is loader-side; failures arrive via events:\nif let ImageLoaderError::ArrayLayout(e) = &*ev.error {\n    error!(\"array reinterpretation failed: {e}\"); // fix sheet dimensions or meta settings\n}","preventionTips":["Author sprite stacks at exact multiples of the row/tile size (authoring templates with fixed grid sizes helps).","Double-check rows vs columns order in GridCount meta.","Only apply array_layout to single-layer uncompressed 2D images."],"tags":["bevy","texture-array","sprite-sheet","asset-loading","rust"],"backgroundTag":"invalid-texture-array-layout","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}