siyuan-note/siyuan · error
decode image failed
Error message
decode image failed: %s
What it means
Identical message to 2211 but thrown at kernel/util/openai.go:787 after imaging.Decode (with auto-orientation applied) fails, i.e. the header parsed via DecodeConfig but the full pixel data cannot be decoded by the imaging library. The library-specific reason is appended to the message.
Solutions
- Re-export/re-encode the image with a standard tool (e.g. convert to baseline JPEG or PNG) and retry
- Check the file size against the source to detect truncation; re-sync or re-download the asset
- Open the file in a viewer to confirm it is valid before sending it to the AI feature
- Inspect the appended reason in the message to identify the specific decoder complaint
Example fix
// before: trusting the header parse
img, err := prepareImage(truncatedBytes, "image/jpeg", ...)
// after: verify full decodability first
if _, err := imaging.Decode(bytes.NewReader(truncatedBytes)); err != nil {
return fmt.Errorf("source image is corrupt: %w", err)
}
img, err := prepareImage(truncatedBytes, "image/jpeg", ...) Defensive patterns
Strategy: validation
Validate before calling
if _, err := imaging.Decode(bytes.NewReader(data)); err != nil {
return fmt.Errorf("source image is corrupt: %w", err)
} Prevention
- Full-decode the image before sending it to processing that will decode again
- Compare on-disk size with the source size to catch truncation early
- Re-encode suspicious images once with a standard tool (fixes most variant issues)
- Keep sync/backup tooling from writing partial asset files
When it happens
Trigger: Feeding an image whose full decode fails even though DecodeConfig succeeded: truncated pixel data, corrupt IDAT/scan segments, unsupported EXIF-heavy or progressive variants, or CMYK JPEGs the decoder rejects.
Common situations: Partially synced asset files; images stripped or mangled by an external processor; exotic JPEG variants (CMYK, lossless) or animated WebP edge cases failing imaging.Decode.
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
- unsupported or invalid image
- encode image failed
- generated image exceeds size limit
- generated image is empty
- generated image is invalid
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/88a6847d1525d5e2.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/openai.go:787
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 9f775e8a12)