{"record":{"id":"931951e2942c8885","repo":"siyuan-note/siyuan","slug":"image-data-is-empty","errorCode":null,"errorMessage":"image data is empty","messagePattern":"image data is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai.go","lineNumber":763,"sourceCode":"\t\terr = fmt.Errorf(\"rerank returned %d indices for %d documents\", len(indices), len(documents))\n\t\treturn\n\t}\n\tseen := make(map[int]bool, len(indices))\n\tfor _, index := range indices {\n\t\tif seen[index] {\n\t\t\terr = fmt.Errorf(\"rerank returned duplicate index %d\", index)\n\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) {","sourceCodeStart":745,"sourceCodeEnd":781,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/openai.go#L745-L781","documentation":"PrepareModelImage in kernel/util/openai.go rejects empty image byte slices up front. Multimodal model upload paths call this to validate and scale images before sending; zero-length data can never be a valid image. The error is returned immediately as PreparedImage{} with a descriptive message.","triggerScenarios":"Calling PrepareModelImage (or the multimodal attach flow that uses it) with a nil or empty []byte — e.g. an asset file that failed to read, an empty download, or a zero-length attachment in an AI chat.","commonSituations":"Asset file deleted from disk after being referenced in the chat; interrupted download cached as an empty file; reading an asset with the wrong path; clipboard paste producing an empty buffer.","solutions":["Check the source asset exists and has non-zero size before invoking the image pipeline","Re-download or re-copy the asset; an empty file on disk is itself corrupted","Verify the path resolution that produced the []byte — a wrong path often yields an empty read without failing loudly"],"exampleFix":"// before\ndata, _ := os.ReadFile(assetPath)\nprepared, err := PrepareModelImage(data, maxBytes, maxPixels, maxEdge)\n// after\ndata, err := os.ReadFile(assetPath)\nif err != nil || len(data) == 0 {\n    return fmt.Errorf(\"asset %s is missing or empty\", assetPath)\n}\nprepared, err := PrepareModelImage(data, maxBytes, maxPixels, maxEdge)","handlingStrategy":"validation","validationCode":"if data == nil || len(data) == 0 { return errors.New(\"image asset is empty; re-check the file\") }","typeGuard":"func hasImageBytes(b []byte) bool { return len(b) > 0 }","tryCatchPattern":"prepared, err := PrepareModelImage(data, maxBytes, maxPixels, maxEdge)\nif err != nil && strings.Contains(err.Error(), \"empty\") {\n    return reFetchAssetAndRetry()\n}","preventionTips":["Check os.ReadFile's error and byte count before passing data along","Validate asset integrity at import time so empty files never enter the library","Verify asset paths resolve within the workspace data dir"],"tags":["image","validation","multimodal"],"backgroundTag":"empty-required-field","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"}