{"record":{"id":"8a0e668bf2652b16","repo":"d2lang/d2","slug":"decoded-gif-image-could-not-be-cast-as-image-pale","errorCode":null,"errorMessage":"decoded gif image could not be cast as *image.Paletted","messagePattern":"decoded gif image could not be cast as \\*image\\.Paletted","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/xgif/xgif.go","lineNumber":144,"sourceCode":"\t\ti := i\n\t\tg.Go(func() error {\n\t\t\tpngImage := pngImgs[i]\n\t\t\t// 1. convert the PNG into a GIF compatible image (Bitmap) by quantizing it to 255 colors\n\t\t\tbuf := bytes.NewBuffer(nil)\n\t\t\terr := gif.Encode(buf, pngImage, &gif.Options{\n\t\t\t\tNumColors: 256, // GIFs can have up to 256 colors\n\t\t\t\tQuantizer: quantize.MedianCutQuantizer{},\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tgifImg, err := gif.Decode(buf)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tpalettedImg, ok := gifImg.(*image.Paletted)\n\t\t\tif !ok {\n\t\t\t\treturn fmt.Errorf(\"decoded gif image could not be cast as *image.Paletted\")\n\t\t\t}\n\n\t\t\t// 2. make GIF frames of the same size, keeping images centered and with a white background\n\t\t\tbounds := pngImage.Bounds()\n\t\t\ttop := (height - bounds.Dy()) / 2\n\t\t\tbottom := top + bounds.Dy()\n\t\t\tleft := (width - bounds.Dx()) / 2\n\t\t\tright := left + bounds.Dx()\n\n\t\t\tvar bgIndex int\n\t\t\tif len(palettedImg.Palette) == 256 {\n\t\t\t\tbgIndex = findWhiteIndex(palettedImg.Palette)\n\t\t\t\tpalettedImg.Palette[bgIndex] = BG_COLOR\n\t\t\t} else {\n\t\t\t\tbgIndex = len(palettedImg.Palette)\n\t\t\t\tpalettedImg.Palette = append(palettedImg.Palette, BG_COLOR)\n\t\t\t}\n\t\t\tframe := image.NewPaletted(image.Rect(0, 0, width, height), palettedImg.Palette)","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/lib/xgif/xgif.go#L126-L162","documentation":"After re-encoding each PNG frame through gif.Encode, xgif decodes it again expecting the result to be an *image.Paletted, which the standard library's gif decoder normally returns. If the decoded image is not *image.Paletted, the animation builder cannot use it for palette-indexed GIF frames and returns this error.","triggerScenarios":"gif.Decode returns an image type other than *image.Paletted — practically only if the standard library behavior changes, the buffer was altered between encode and decode, or a custom decoder is registered for the GIF format that returns a different image type.","commonSituations":"Building with a modified or nonstandard image/gif package; a GIF registered via image.RegisterFormat overriding decoding; extremely exotic inputs to the xgif conversion API.","solutions":["Ensure the standard library image/gif decoder is used (no custom RegisterFormat overrides for GIF)","Verify the bytes being decoded are the GIF produced by gif.Encode immediately above","Update Go to a current version; a change in gif.Decode return type would be a stdlib anomaly","If reproducing, inspect gifImg's concrete type via %T and file a bug"],"exampleFix":"gifImg, err := gif.Decode(buf)\nif err != nil { return err }\npalettedImg, ok := gifImg.(*image.Paletted)\nif !ok {\n    return fmt.Errorf(\"decoded gif image could not be cast as *image.Paletted (got %T)\", gifImg)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"palettedImg, ok := gifImg.(*image.Paletted)\nif !ok {\n    return fmt.Errorf(\"unexpected decoded frame type %T\", gifImg)\n}","tryCatchPattern":"if err := pngsToGif(frames, opts); err != nil {\n    if strings.Contains(err.Error(), \"could not be cast as *image.Paletted\") {\n        return retryWithStandardDecoder(frames)\n    }\n    return err\n}","preventionTips":["Don't register custom decoders for the GIF format via image.RegisterFormat","Use the standard library image/gif package unchanged","Keep Go toolchain current","Log the concrete type (%T) when this occurs to diagnose decoder interference"],"tags":["gif","image","encoding","go-stdlib"],"backgroundTag":"unexpected-image-type","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}