siyuan-note/siyuan · error
decode image failed: %s
Error message
decode image failed: %s
What it means
PrepareModelImage wraps the disintegration/imaging library's Decode failure with the message "decode image failed: %s" (kernel/util/openai.go:763). The data has already passed magic-byte MIME detection and DecodeConfig checks, so this error means the full pixel decode (with EXIF auto-orientation) failed — typically a truncated, corrupted, or partially-downloaded image whose header parsed fine but whose body does not.
Source
Thrown at kernel/util/openai.go:763
if strings.Contains(mimeType, "svg") || bytes.Contains(bytes.ToLower(data[:min(len(data), 512)]), []byte("<svg")) {
return PreparedImage{}, errors.New("SVG images are not accepted by multimodal models")
}
switch mimeType {
case "image/gif", "image/jpeg", "image/png", "image/webp":
default:
return PreparedImage{}, fmt.Errorf("unsupported image type: %s", mimeType)
}
config, _, err := image.DecodeConfig(bytes.NewReader(data))
if err != nil {
return PreparedImage{}, errors.New("unsupported or invalid image: " + err.Error())
}
if config.Width < 1 || config.Height < 1 || maxPixels > 0 && int64(config.Width)*int64(config.Height) > int64(maxPixels) {
return PreparedImage{}, fmt.Errorf("image exceeds pixel limit: %d", maxPixels)
}
decoded, err := imaging.Decode(bytes.NewReader(data), imaging.AutoOrientation(true))
if err != nil {
return PreparedImage{}, errors.New("decode image failed: " + err.Error())
}
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.BufferView on GitHub (pinned to 8641553a1f)
Solutions
- Re-obtain or re-download the image file; verify the source file opens in a normal image viewer and is not truncated.
- Inspect the wrapped underlying error in the message to identify the exact decoder failure (e.g. 'short Huffman data', 'unexpected EOF').
- Re-encode the image once with a standard tool (e.g. convert to PNG/JPEG) before sending it to a multimodal model.
- If the format is exotic (progressive/lossless webp variants, 16-bit PNG), convert it to a baseline JPEG or PNG first.
Example fix
// before: sending raw bytes read from an interrupted download
prepared, err := util.PrepareModelImage(data, maxBytes, maxPixels, maxEdge)
// after: verify the image fully decodes before use
if _, err := imaging.Decode(bytes.NewReader(data)); err != nil {
// re-download or re-encode the source image
}
prepared, err := util.PrepareModelImage(data, maxBytes, maxPixels, maxEdge) Defensive patterns
Strategy: validation
Validate before calling
func isDecodableImage(data []byte) bool {
_, err := imaging.Decode(bytes.NewReader(data), imaging.AutoOrientation(true))
return err == nil
} Try / catch
prepared, err := util.PrepareModelImage(data, maxBytes, maxPixels, maxEdge)
if err != nil && strings.HasPrefix(err.Error(), "decode image failed") {
// re-download/re-encode the source before giving up
} Prevention
- Verify downloaded images are complete (compare Content-Length or checksum) before processing
- Re-encode images from untrusted or network sources to baseline PNG/JPEG before passing them in
- Handle partial writes atomically: never process an image file while it is still being written
When it happens
Trigger: Calling PrepareModelImage with image bytes whose header is valid enough for mimetype.Detect and image.DecodeConfig but which fail full decoding: truncated files, corrupted pixel data, unsupported CMYK/YCbCr edge cases, or a format the imaging library cannot handle even though the kernel registered a decoder for it.
Common situations: Downloads interrupted mid-transfer; assets modified or partially written to disk; clipboard-saved image fragments; an image whose earlier DecodeConfig succeeded (headers intact) but the trailing chunks are damaged; registering a format decoder (e.g. webp) that decodes configs but not full images in the imaging library.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/88a6847d1525d5e2.
Report an issue: GitHub.