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
- Retry with the original image after confirming it decodes correctly; the error is rarely caused by the input format.
- Check available memory — resizing very large images via imaging.Fit with Lanczos plus PNG encoding is memory-heavy; reduce maxEdge or image dimensions.
- Inspect the wrapped error text; if it indicates memory/write failure, increase system resources or pre-shrink the image externally.
- 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
- Bound input image dimensions before calling so resize+encode stays within memory limits
- Monitor available memory in constrained environments when processing large PNG/WebP images
- Fall back to a plain JPEG path if PNG re-encoding repeatedly fails
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.