{"record":{"id":"3608834169716ea5","repo":"plandex-ai/plandex","slug":"failed-to-decode-image-config-w","errorCode":null,"errorMessage":"failed to decode image config: %w","messagePattern":"failed to decode image config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/shared/images.go","lineNumber":38,"sourceCode":"\t_ \"golang.org/x/image/webp\"\n)\n\nfunc GetImageTokens(base64Image string, detail openai.ImageURLDetail) (int, error) {\n\timageData, err := base64.StdEncoding.DecodeString(base64Image)\n\tif err != nil {\n\t\tlog.Println(\"failed to decode base64 image data:\", err)\n\t\treturn 0, fmt.Errorf(\"failed to decode base64 image data: %w\", err)\n\t}\n\n\treturn GetImageTokensFromHeader(bytes.NewReader(imageData), detail, int64(len(imageData)))\n}\n\nfunc GetImageTokensFromHeader(reader io.Reader, detail openai.ImageURLDetail, maxBytes int64) (int, error) {\n\treader = io.LimitReader(reader, maxBytes)\n\timg, _, err := image.DecodeConfig(reader)\n\tif err != nil {\n\t\tlog.Println(\"failed to decode image config:\", err)\n\t\treturn 0, fmt.Errorf(\"failed to decode image config: %w\", err)\n\t}\n\n\twidth, height := img.Width, img.Height\n\n\tanthropicTokens := getAnthropicImageTokens(width, height)\n\tgoogleTokens := getGoogleImageTokens(width, height)\n\topenaiTokens := getOpenAIImageTokens(width, height, detail)\n\n\t// log.Printf(\"GetImageTokens - width: %d, height: %d\\n\", width, height)\n\t// log.Printf(\"GetImageTokens - anthropicTokens: %d\\n\", anthropicTokens)\n\t// log.Printf(\"GetImageTokens - googleTokens: %d\\n\", googleTokens)\n\t// log.Printf(\"GetImageTokens - openaiTokens: %d\\n\", openaiTokens)\n\n\t// get max of the three\n\treturn int(math.Max(\n\t\tfloat64(anthropicTokens),\n\t\tmath.Max(\n\t\t\tfloat64(googleTokens),","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/shared/images.go#L20-L56","documentation":"After decoding, GetImageTokensFromHeader calls image.DecodeConfig, which sniffs the image header (gif/jpeg/png/webp registered via blank imports) to read dimensions. This error means the bytes are not a decodable/registered image format or the header is corrupt/truncated.","triggerScenarios":"Passing decoded bytes whose format is not registered (e.g. SVG, TIFF, AVIF, HEIC); corrupt or truncated image data; an empty reader; maxBytes too small so DecodeConfig cannot read a full header.","commonSituations":"Users uploading SVGs or AVIF images which the model pipeline treats as images but image.DecodeConfig cannot parse; partially uploaded files; wrong maxBytes argument clipping the header.","solutions":["Register additional decoders with blank imports (e.g. _ \"golang.org/x/image/tiff\") if the format is supported upstream.","Reject or skip unsupported formats (SVG, AVIF, HEIC) with a user-facing validation before token estimation.","Validate that the image bytes begin with a known magic number (PNG \\x89PNG, JPEG \\xFF\\xD8, GIF87a/GIF89a, RIFF....WEBP) before calling.","Ensure maxBytes covers the full header (pass the complete byte length, as GetImageTokens does with int64(len(imageData)))."],"exampleFix":"// before\n_, _, err := image.DecodeConfig(bytes.NewReader(raw)) // fails for SVG/AVIF\n// after\nif !isValidImageMagic(raw) { // check PNG/JPEG/GIF/WEBP magic bytes\n    return fmt.Errorf(\"unsupported image format\")\n}\nimg, _, err := image.DecodeConfig(bytes.NewReader(raw))","handlingStrategy":"validation","validationCode":"func hasKnownImageMagic(b []byte) bool {\n    if len(b) < 12 { return false }\n    png := bytes.HasPrefix(b, []byte{\"\\x89PNG\\r\\n\\x1a\\n\"})\n    jpeg := bytes.HasPrefix(b, []byte{\"\\xFF\\xD8\\xFF\"})\n    gif := bytes.HasPrefix(b, []byte(\"GIF87a\")) || bytes.HasPrefix(b, []byte(\"GIF89a\"))\n    webp := bytes.HasPrefix(b, []byte(\"RIFF\")) && bytes.Equal(b[8:12], []byte(\"WEBP\"))\n    return png || jpeg || gif || webp\n}","typeGuard":null,"tryCatchPattern":"tokens, err := shared.GetImageTokens(payload, detail)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to decode image config\") {\n        return fmt.Errorf(\"unsupported or corrupt image (use PNG/JPEG/GIF/WEBP): %w\", err)\n    }\n    return err\n}","preventionTips":["Only accept PNG, JPEG, GIF, and WEBP uploads; reject SVG/AVIF/HEIC explicitly.","Verify magic bytes in the upload handler before persisting.","Ensure uploads are complete (check content-length vs received bytes).","Pass the full payload length as maxBytes so headers are never clipped."],"tags":["image","go","decoding","format"],"backgroundTag":"invalid-image-format","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}