plandex-ai/plandex · error

failed to decode image config: %w

Error message

failed to decode image config: %w

What it means

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.

Source

Thrown at app/shared/images.go:38

	_ "golang.org/x/image/webp"
)

func GetImageTokens(base64Image string, detail openai.ImageURLDetail) (int, error) {
	imageData, err := base64.StdEncoding.DecodeString(base64Image)
	if err != nil {
		log.Println("failed to decode base64 image data:", err)
		return 0, fmt.Errorf("failed to decode base64 image data: %w", err)
	}

	return GetImageTokensFromHeader(bytes.NewReader(imageData), detail, int64(len(imageData)))
}

func GetImageTokensFromHeader(reader io.Reader, detail openai.ImageURLDetail, maxBytes int64) (int, error) {
	reader = io.LimitReader(reader, maxBytes)
	img, _, err := image.DecodeConfig(reader)
	if err != nil {
		log.Println("failed to decode image config:", err)
		return 0, fmt.Errorf("failed to decode image config: %w", err)
	}

	width, height := img.Width, img.Height

	anthropicTokens := getAnthropicImageTokens(width, height)
	googleTokens := getGoogleImageTokens(width, height)
	openaiTokens := getOpenAIImageTokens(width, height, detail)

	// log.Printf("GetImageTokens - width: %d, height: %d\n", width, height)
	// log.Printf("GetImageTokens - anthropicTokens: %d\n", anthropicTokens)
	// log.Printf("GetImageTokens - googleTokens: %d\n", googleTokens)
	// log.Printf("GetImageTokens - openaiTokens: %d\n", openaiTokens)

	// get max of the three
	return int(math.Max(
		float64(anthropicTokens),
		math.Max(
			float64(googleTokens),

View on GitHub (pinned to e2d772072e)

Solutions

  1. Register additional decoders with blank imports (e.g. _ "golang.org/x/image/tiff") if the format is supported upstream.
  2. Reject or skip unsupported formats (SVG, AVIF, HEIC) with a user-facing validation before token estimation.
  3. Validate that the image bytes begin with a known magic number (PNG \x89PNG, JPEG \xFF\xD8, GIF87a/GIF89a, RIFF....WEBP) before calling.
  4. Ensure maxBytes covers the full header (pass the complete byte length, as GetImageTokens does with int64(len(imageData))).

Example fix

// before
_, _, err := image.DecodeConfig(bytes.NewReader(raw)) // fails for SVG/AVIF
// after
if !isValidImageMagic(raw) { // check PNG/JPEG/GIF/WEBP magic bytes
    return fmt.Errorf("unsupported image format")
}
img, _, err := image.DecodeConfig(bytes.NewReader(raw))
Defensive patterns

Strategy: validation

Validate before calling

func hasKnownImageMagic(b []byte) bool {
    if len(b) < 12 { return false }
    png := bytes.HasPrefix(b, []byte{"\x89PNG\r\n\x1a\n"})
    jpeg := bytes.HasPrefix(b, []byte{"\xFF\xD8\xFF"})
    gif := bytes.HasPrefix(b, []byte("GIF87a")) || bytes.HasPrefix(b, []byte("GIF89a"))
    webp := bytes.HasPrefix(b, []byte("RIFF")) && bytes.Equal(b[8:12], []byte("WEBP"))
    return png || jpeg || gif || webp
}

Try / catch

tokens, err := shared.GetImageTokens(payload, detail)
if err != nil {
    if strings.Contains(err.Error(), "failed to decode image config") {
        return fmt.Errorf("unsupported or corrupt image (use PNG/JPEG/GIF/WEBP): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/3608834169716ea5. Report an issue: GitHub.