{"record":{"id":"0b57b571c67bee48","repo":"OpenRA/OpenRA","slug":"invalid-plte-chunk-length","errorCode":null,"errorMessage":"Invalid PLTE chunk length.","messagePattern":"Invalid PLTE chunk length\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"OpenRA.Game/FileFormats/Png.cs","lineNumber":184,"sourceCode":"\n\t\t\t\t\t\tif (compression != 0)\n\t\t\t\t\t\t\tthrow new InvalidDataException(\"Compression method not supported\");\n\n\t\t\t\t\t\tif (interlace != 0)\n\t\t\t\t\t\t\tthrow new InvalidDataException(\"Interlacing not supported\");\n\n\t\t\t\t\t\tData = new byte[Width * Height * PixelStride];\n\n\t\t\t\t\t\t// Skip CRC.\n\t\t\t\t\t\ts.Seek(4, SeekOrigin.Current);\n\t\t\t\t\t\theaderParsed = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase ChunkPLTE:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (length % 3 != 0)\n\t\t\t\t\t\t\tthrow new InvalidDataException(\"Invalid PLTE chunk length.\");\n\n\t\t\t\t\t\tvar count = length / 3;\n\t\t\t\t\t\tPalette = new Color[count];\n\n\t\t\t\t\t\tvar buffer = ArrayPool<byte>.Shared.Rent(length);\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ts.ReadBytes(buffer.AsSpan(0, length));\n\t\t\t\t\t\t\tfor (var i = 0; i < count; i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar offset = i * 3;\n\t\t\t\t\t\t\t\tPalette[i] = Color.FromArgb(buffer[offset], buffer[offset + 1], buffer[offset + 2]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tArrayPool<byte>.Shared.Return(buffer);\n\t\t\t\t\t\t}","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/OpenRA/OpenRA/blob/a520984d91eda9de48a62b1d15c1e3bad0d4fb1a/OpenRA.Game/FileFormats/Png.cs#L166-L202","documentation":"Thrown by Png(Stream) when a PLTE (palette) chunk's declared length is not evenly divisible by 3. Each palette entry is an RGB triplet (3 bytes), so the total length must be length % 3 == 0. A non-multiple-of-3 length means the palette data is malformed.","triggerScenarios":"Constructing `new Png(stream)` where an indexed-color PNG has a PLTE chunk whose 4-byte big-endian length field is not divisible by 3. The code checks `length % 3 != 0` immediately upon encountering ChunkPLTE.","commonSituations":"Byte-level corruption in the PLTE chunk's length field. A broken PNG encoder that wrote an incorrect length. File truncation or modification that shifted bytes within the PLTE chunk.","solutions":["Re-export the PNG from the original indexed-color source image.","Run pngcheck to validate palette chunk integrity.","Replace the corrupt file with a clean copy from version control or backup."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    var png = new Png(stream);\n}\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"PLTE chunk length\"))\n{\n    logger.LogError($\"Corrupt PNG palette: {ex.Message}\");\n}","preventionTips":["Re-export indexed PNGs from source images rather than manually editing palette data.","Run pngcheck on all indexed PNG assets during CI.","Store original source images (e.g., PSD, XCF) to regenerate assets if corruption occurs."],"tags":["png","file-format","corruption","palette"],"backgroundTag":null,"analyzedSha":"a520984d91eda9de48a62b1d15c1e3bad0d4fb1a","analyzedAt":"2026-08-13T15:30:14.787Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}