siyuan-note/siyuan · error

encode image failed: %s

Error message

encode image failed: %s

What it means

When the source image is PNG or WebP and needed resizing/re-encoding, PrepareModelImage re-encodes the decoded image with Go's image/png encoder; an encoder failure is wrapped as "encode image failed: %s" (kernel/util/openai.go:783). PNG encoding of a valid in-memory image essentially only fails on buffer write errors, so this is very rare and usually signals an underlying I/O or memory problem.

Source

Thrown at kernel/util/openai.go:783

	bounds := decoded.Bounds()
	needsResize := maxEdge > 0 && (bounds.Dx() > maxEdge || bounds.Dy() > maxEdge)
	if !needsResize && bounds.Dx() == config.Width && bounds.Dy() == config.Height && mimeType != "image/gif" {
		return PreparedImage{
			Data:       data,
			MIMEType:   mimeType,
			Width:      bounds.Dx(),
			Height:     bounds.Dy(),
			SourceSize: len(data),
		}, nil
	}
	if needsResize {
		decoded = imaging.Fit(decoded, maxEdge, maxEdge, imaging.Lanczos)
	}
	bounds = decoded.Bounds()
	if mimeType == "image/png" || mimeType == "image/webp" {
		var output bytes.Buffer
		if err = png.Encode(&output, decoded); err != nil {
			return PreparedImage{}, errors.New("encode image failed: " + err.Error())
		}
		if maxBytes <= 0 || output.Len() <= maxBytes {
			return PreparedImage{
				Data:       output.Bytes(),
				MIMEType:   "image/png",
				Width:      bounds.Dx(),
				Height:     bounds.Dy(),
				SourceSize: len(data),
			}, nil
		}
	}
	var output bytes.Buffer
	if err = jpeg.Encode(&output, decoded, &jpeg.Options{Quality: 92}); err != nil {
		return PreparedImage{}, errors.New("encode image failed: " + err.Error())
	}
	if maxBytes > 0 && output.Len() > maxBytes {
		return PreparedImage{}, fmt.Errorf("prepared image exceeds size limit: %d bytes", maxBytes)
	}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Retry with the original image after confirming it decodes correctly; the error is rarely caused by the input format.
  2. Check available memory — resizing very large images via imaging.Fit with Lanczos plus PNG encoding is memory-heavy; reduce maxEdge or image dimensions.
  3. Inspect the wrapped error text; if it indicates memory/write failure, increase system resources or pre-shrink the image externally.
  4. As a workaround, convert the source to JPEG beforehand so the code path uses jpeg.Encode instead.
Defensive patterns

Strategy: try-catch

Try / catch

prepared, err := util.PrepareModelImage(data, maxBytes, maxPixels, maxEdge)
if err != nil && strings.HasPrefix(err.Error(), "encode image failed") {
    // retry once; otherwise fall back to sending a pre-shrunk JPEG
}

Prevention

When it happens

Trigger: PrepareModelImage is called with a PNG or WebP image that requires resizing (larger than maxEdge) or a re-encode (e.g. WebP needing re-encode to PNG), and image/png's Encode returns an error while writing to the bytes.Buffer.

Common situations: Extremely large images causing memory pressure while encoding; a corrupted decoded image state from the imaging library; out-of-memory conditions on constrained environments during Lanczos resize + encode.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/946a1fba26e51597. Report an issue: GitHub.