{"record":{"id":"90e471907c5e6fc8","repo":"siyuan-note/siyuan","slug":"svg-images-are-not-accepted-by-multimodal-models","errorCode":null,"errorMessage":"SVG images are not accepted by multimodal models","messagePattern":"SVG images are not accepted by multimodal models","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai.go","lineNumber":770,"sourceCode":"\t\t\treturn\n\t\t}\n\t\tseen[index] = true\n\t}\n\tmatched = true\n\treturn\n}\n\n// PrepareModelImage 校验并按需缩放图片，尽量保留多模态模型支持的原始格式和图片质量。\nfunc 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}","sourceCodeStart":752,"sourceCodeEnd":788,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/openai.go#L752-L788","documentation":"PrepareModelImage rejects SVG images because multimodal model APIs do not accept vector SVG payloads. Detection is twofold: the mimetype library's result containing 'svg', or a literal '<svg' byte sequence in the first 512 bytes. This catches both properly typed SVG files and SVG content served with a wrong or missing content type.","triggerScenarios":"Calling PrepareModelImage on an .svg asset — e.g. dragging an SVG icon/diagram into an AI chat with a multimodal model, or an asset whose first 512 bytes contain '<svg'.","commonSituations":"Inserting icons, logos, or mermaid/plantuml-exported SVG diagrams then referencing them in AI chats; assets saved from the web with SVG content but a PNG-like name.","solutions":["Convert the SVG to PNG (or JPEG/WebP) before attaching it to an AI conversation","Render the SVG at a target resolution with a rasterizer (browser, resvg, sharp) and use the raster output","If the image is a diagram, export it from the diagram tool directly as PNG instead of SVG","If you only need the content described, paste the SVG's source text into the chat instead of attaching it as an image"],"exampleFix":"// before\nprepared, err := PrepareModelImage(svgBytes, maxBytes, maxPixels, maxEdge) // SVG rejected\n// after\npngBytes := rasterizeSVG(svgBytes, 1024, 1024) // render to PNG first\nprepared, err := PrepareModelImage(pngBytes, maxBytes, maxPixels, maxEdge)","handlingStrategy":"validation","validationCode":"if bytes.Contains(bytes.ToLower(data[:min(len(data),512)]), []byte(\"<svg\")) {\n    data = rasterizeSVG(data, 1024) // convert before the pipeline rejects it\n}","typeGuard":"func isRasterImage(mt string) bool {\n    switch mt {\n    case \"image/gif\", \"image/jpeg\", \"image/png\", \"image/webp\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"prepared, err := PrepareModelImage(data, maxBytes, maxPixels, maxEdge)\nif err != nil && strings.Contains(err.Error(), \"SVG\") {\n    prepared, err = PrepareModelImage(rasterizeSVG(data, 1024), maxBytes, maxPixels, maxEdge)\n}","preventionTips":["Prefer PNG/JPEG exports when inserting diagrams intended for AI chats","Do not name SVG files with image extensions expecting them to work as raster images","Run mimetype detection at import time and flag SVG assets as non-attachable"],"tags":["image","svg","multimodal"],"backgroundTag":"unsupported-source-type","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"}