{"record":{"id":"f6936d664807ae37","repo":"JuliusBrussee/caveman","slug":"encodegraypng-pixels-length-d-dx-d","errorCode":null,"errorMessage":"encodeGrayPNG: pixels length %d != %dx%d","messagePattern":"encodeGrayPNG: pixels length (.+?) != (.+?)x(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/pixel/png.go","lineNumber":27,"sourceCode":"\t\"image/color\"\n\t\"image/png\"\n)\n\ntype RenderedImage struct {\n\tPNG               []byte\n\tWidth, Height     int\n\tCharsRendered     int\n\tDroppedChars      int\n\tDroppedCodepoints map[rune]int\n\t// Layers is the number of interleaved text layers baked into this image: 1\n\t// for an ordinary page, 2 for a max-level red/blue overlay page. Zero is\n\t// treated as 1 by callers (existing single-layer renderers leave it unset).\n\tLayers int\n}\n\nfunc encodeGrayPNG(pixels []uint8, width, height int) ([]byte, error) {\n\tif len(pixels) != width*height {\n\t\treturn nil, fmt.Errorf(\"encodeGrayPNG: pixels length %d != %dx%d\", len(pixels), width, height)\n\t}\n\timg := image.NewGray(image.Rect(0, 0, width, height))\n\tcopy(img.Pix, pixels)\n\tvar buf bytes.Buffer\n\tif err := png.Encode(&buf, img); err != nil {\n\t\treturn nil, err\n\t}\n\treturn buf.Bytes(), nil\n}\n\nfunc encodeRGBPNG(pixels []uint8, width, height int) ([]byte, error) {\n\tif len(pixels) != width*height*3 {\n\t\treturn nil, fmt.Errorf(\"encodeRGBPNG: pixels length %d != %dx%dx3\", len(pixels), width, height)\n\t}\n\timg := image.NewNRGBA(image.Rect(0, 0, width, height))\n\tfor i := 0; i < width*height; i++ {\n\t\timg.SetNRGBA(i%width, i/width, color.NRGBA{\n\t\t\tR: pixels[i*3],","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/engine/pixel/png.go#L9-L45","documentation":"Raised by encodeGrayPNG: the grayscale pixel buffer length does not equal width*height. It is a caller-contract guard in the PNG rasterizer — the pixel slice was built with different dimensions than passed, so encoding would read out of bounds or truncate rows.","triggerScenarios":"Thrown at engine/pixel/png.go:27 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the pixel slice has exactly width*height entries before calling encodeGrayPNG","Allocate pixels with make([]uint8, width*height) at the same dimensions passed to the renderer","Fix the renderer that produced a mismatched buffer (check stride/row padding)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}