d2lang/d2 · error

error decoding PNG image: %v

Error message

error decoding PNG image: %v

What it means

Presentation.AddSlide decodes the provided PNG bytes with the png decoder before embedding them into a slide; if decoding fails (invalid, truncated, or non-PNG data), the error is wrapped with this message. The library requires valid PNG image content for each slide.

Source

Thrown at lib/pptx/pptx.go:107

func (p *Presentation) headerHeight() int {
	if p.includeNav {
		return HEADER_HEIGHT
	}
	return 0
}

func (p *Presentation) height() int {
	return SLIDE_HEIGHT - p.headerHeight()
}

func (p *Presentation) aspectRatio() float64 {
	return float64(IMAGE_WIDTH) / float64(p.height())
}

func (p *Presentation) AddSlide(pngContent []byte, titlePath []BoardTitle) (*Slide, error) {
	src, err := png.Decode(bytes.NewReader(pngContent))
	if err != nil {
		return nil, fmt.Errorf("error decoding PNG image: %v", err)
	}

	var width, height int
	srcSize := src.Bounds().Size()
	srcWidth, srcHeight := float64(srcSize.X), float64(srcSize.Y)

	// compute the size and position to fit the slide
	// if the image is wider than taller and its aspect ratio is, at least, the same as the available image space aspect ratio
	// then, set the image width to the available space and compute the height
	// ┌──────────────────────────────────────────────────┐   ─┬─
	// │  HEADER                                          │    │
	// ├──┬────────────────────────────────────────────┬──┤    │         ─┬─
	// │  │                                            │  │    │          │
	// │  │                                            │  │  SLIDE        │
	// │  │                                            │  │  HEIGHT       │
	// │  │                                            │  │    │        IMAGE
	// │  │                                            │  │    │        HEIGHT
	// │  │                                            │  │    │          │

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Validate the PNG before calling AddSlide (png.DecodeConfig or magic-bytes check \x89PNG)
  2. Check the upstream rendering step's error/status before using its bytes
  3. Ensure the file was read completely (compare bytes read vs file size)
  4. Confirm the source is actually PNG, not JPEG/SVG
  5. Log the first bytes of pngContent to diagnose what was actually passed

Example fix

// before
slide, err := pptx.AddSlide(pngBytes, titles)
// after
if len(pngBytes) < 8 || string(pngBytes[:8]) != "\x89PNG\r\n\x1a\n" {
    return fmt.Errorf("not a valid PNG (%d bytes)", len(pngBytes))
}
slide, err := pptx.AddSlide(pngBytes, titles)
Defensive patterns

Strategy: validation

Validate before calling

func isPNG(b []byte) bool {
    return len(b) >= 8 && b[0]==0x89 && b[1]=='P' && b[2]=='N' && b[3]=='G' && b[4]==0x0d && b[5]==0x0a && b[6]==0x1a && b[7]==0x0a
}
if !isPNG(pngBytes) { return errors.New("invalid PNG input") }

Type guard

func validPNG(b []byte) bool {
    _, err := png.DecodeConfig(bytes.NewReader(b))
    return err == nil
}

Try / catch

slide, err := pres.AddSlide(pngBytes, titles)
if err != nil {
    if strings.Contains(err.Error(), "error decoding PNG") {
        log.Printf("bad png (%d bytes, head=%x)", len(pngBytes), pngBytes[:min(8,len(pngBytes))])
        return reRenderImage()
    }
    return err
}

Prevention

When it happens

Trigger: Passing empty/nil byte slices, corrupted/truncated PNG files, or non-PNG data (JPEG, SVG text, HTML error pages) as pngContent to AddSlide — typically the output of a rendering pipeline that failed.

Common situations: Upstream renderer returned an error page captured as bytes; file read was truncated; wrong file extension fed in; an export step silently produced empty output.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/ff8c4c4c4eeec1ae. Report an issue: GitHub.