{"record":{"id":"a916b85b345ebe0d","repo":"siyuan-note/siyuan","slug":"unsupported-or-invalid-image-s","errorCode":null,"errorMessage":"unsupported or invalid image: %s","messagePattern":"unsupported or invalid image: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai.go","lineNumber":779,"sourceCode":"func PrepareModelImage(data []byte, maxBytes, maxPixels, maxEdge int) (PreparedImage, error) {\n\tif len(data) == 0 {\n\t\treturn PreparedImage{}, errors.New(\"image data is empty\")\n\t}\n\tif maxBytes > 0 && len(data) > maxBytes {\n\t\treturn PreparedImage{}, fmt.Errorf(\"image exceeds size limit: %d bytes\", maxBytes)\n\t}\n\tmimeType := mimetype.Detect(data).String()\n\tif strings.Contains(mimeType, \"svg\") || bytes.Contains(bytes.ToLower(data[:min(len(data), 512)]), []byte(\"<svg\")) {\n\t\treturn PreparedImage{}, errors.New(\"SVG images are not accepted by multimodal models\")\n\t}\n\tswitch mimeType {\n\tcase \"image/gif\", \"image/jpeg\", \"image/png\", \"image/webp\":\n\tdefault:\n\t\treturn PreparedImage{}, fmt.Errorf(\"unsupported image type: %s\", mimeType)\n\t}\n\tconfig, _, err := image.DecodeConfig(bytes.NewReader(data))\n\tif err != nil {\n\t\treturn PreparedImage{}, errors.New(\"unsupported or invalid image: \" + err.Error())\n\t}\n\tif config.Width < 1 || config.Height < 1 || maxPixels > 0 && int64(config.Width)*int64(config.Height) > int64(maxPixels) {\n\t\treturn PreparedImage{}, fmt.Errorf(\"image exceeds pixel limit: %d\", maxPixels)\n\t}\n\n\tdecoded, err := imaging.Decode(bytes.NewReader(data), imaging.AutoOrientation(true))\n\tif err != nil {\n\t\treturn PreparedImage{}, errors.New(\"decode image failed: \" + err.Error())\n\t}\n\tbounds := decoded.Bounds()\n\tneedsResize := maxEdge > 0 && (bounds.Dx() > maxEdge || bounds.Dy() > maxEdge)\n\tif !needsResize && bounds.Dx() == config.Width && bounds.Dy() == config.Height && mimeType != \"image/gif\" {\n\t\treturn PreparedImage{\n\t\t\tData:       data,\n\t\t\tMIMEType:   mimeType,\n\t\t\tWidth:      bounds.Dx(),\n\t\t\tHeight:     bounds.Dy(),\n\t\t\tSourceSize: len(data),","sourceCodeStart":761,"sourceCodeEnd":797,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/openai.go#L761-L797","documentation":"This error is thrown by the image preparation routine in kernel/util/openai.go when the image bytes fail Go's image.DecodeConfig after the MIME type already passed the allowed gif/jpeg/png/webp check. It means the data is not decodable as a real image of the declared type — truncated download, corrupt file, or a wrong Content-Type/mime guess. The underlying Go decoder error text is appended to the message.","triggerScenarios":"Passing image bytes whose header does not parse as the declared image/gif, image/jpeg, image/png, or image/webp format into the image preparation function; DecodeConfig returns a parse error such as 'image: unknown format' or 'unexpected EOF'.","commonSituations":"An asset file was truncated or corrupted on disk; a URL fetch returned an HTML error page instead of image bytes; a WEBP variant or HEIC/AVIF photo was mislabeled with an allowed MIME type; sync produced a partial file.","solutions":["Verify the file opens in an image viewer or `file <path>` reports the expected image type","Re-download / re-export the asset to repair truncation or corruption","Check the actual MIME type (magic bytes) and ensure only gif/jpeg/png/webp images are passed in","Convert the image to PNG or JPEG with an external tool before retrying"],"exampleFix":"// before: passing raw fetched bytes blindly\nimg, err := prepareImage(respBytes, \"image/png\", limits...)\n// after: sniff actual format first\nkind := mimetype.Detect(respBytes).String()\nif kind != \"image/png\" && kind != \"image/jpeg\" && kind != \"image/gif\" && kind != \"image/webp\" {\n    return fmt.Errorf(\"not a supported image, got %s\", kind)\n}\nimg, err := prepareImage(respBytes, kind, limits...)","handlingStrategy":"validation","validationCode":"kind := mimetype.Detect(data).String()\nif kind != \"image/png\" && kind != \"image/jpeg\" && kind != \"image/gif\" && kind != \"image/webp\" {\n    return fmt.Errorf(\"unsupported image type: %s\", kind)\n}\ncfg, _, err := image.DecodeConfig(bytes.NewReader(data))\nif err != nil {\n    return fmt.Errorf(\"image not decodable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"prepared, err := util.PrepareImageForAI(data, mime, limits...)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"unsupported or invalid image\") {\n        // drop or re-encode the asset; skip AI vision for it\n        return nil\n    }\n    return err\n}","preventionTips":["Sniff magic bytes (mimetype.Detect) instead of trusting file extensions or Content-Type headers","Verify assets open in a viewer / pass `file` before feeding them to AI features","Re-sync or re-download truncated assets after sync interruptions","Convert HEIC/AVIF photos to JPEG before use"],"tags":["image","decoding","validation","ai"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}