{"record":{"id":"b46d2dd778f1fcd8","repo":"siyuan-note/siyuan","slug":"generated-image-is-empty","errorCode":null,"errorMessage":"generated image is empty","messagePattern":"generated image is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai.go","lineNumber":838,"sourceCode":"\tif err = jpeg.Encode(&output, decoded, &jpeg.Options{Quality: 92}); err != nil {\n\t\treturn PreparedImage{}, errors.New(\"encode image failed: \" + err.Error())\n\t}\n\tif maxBytes > 0 && output.Len() > maxBytes {\n\t\treturn PreparedImage{}, fmt.Errorf(\"prepared image exceeds size limit: %d bytes\", maxBytes)\n\t}\n\treturn PreparedImage{\n\t\tData:       output.Bytes(),\n\t\tMIMEType:   \"image/jpeg\",\n\t\tWidth:      bounds.Dx(),\n\t\tHeight:     bounds.Dy(),\n\t\tSourceSize: len(data),\n\t}, nil\n}\n\n// ValidateGeneratedImage 校验生成图片的格式、尺寸和体积。\nfunc ValidateGeneratedImage(data []byte) (mimeType, extension string, err error) {\n\tif len(data) == 0 {\n\t\treturn \"\", \"\", errors.New(\"generated image is empty\")\n\t}\n\tif len(data) > maxGeneratedImageBytes {\n\t\treturn \"\", \"\", errors.New(\"generated image exceeds size limit\")\n\t}\n\tmimeType = mimetype.Detect(data).String()\n\tswitch mimeType {\n\tcase \"image/png\":\n\t\textension = \".png\"\n\tcase \"image/jpeg\":\n\t\textension = \".jpg\"\n\tcase \"image/webp\":\n\t\textension = \".webp\"\n\tdefault:\n\t\treturn \"\", \"\", fmt.Errorf(\"unsupported generated image type: %s\", mimeType)\n\t}\n\tconfig, _, decodeErr := image.DecodeConfig(bytes.NewReader(data))\n\tif decodeErr != nil || config.Width < 1 || config.Height < 1 || config.Width > 16384 || config.Height > 16384 ||\n\t\tint64(config.Width)*int64(config.Height) > maxGeneratedImagePixels {","sourceCodeStart":820,"sourceCodeEnd":856,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/openai.go#L820-L856","documentation":"ValidateGeneratedImage in kernel/util/openai.go throws this when validating a byte slice returned by an image-generation API and the slice has length 0. It means the adapter produced no image data at all despite (presumably) reporting success.","triggerScenarios":"An AI image-generation response is parsed into an empty byte slice — e.g. an empty b64 field, a missing image payload, or a download of the generated image URL that returned zero bytes.","commonSituations":"Upstream model API changes its response shape; empty b64_json field in the JSON; a signed URL that returned an empty body; base64 decoding of an empty string succeeds silently.","solutions":["Check the raw API response to confirm whether the model actually returned image data","Verify the b64_json / URL field is present and non-empty in the response JSON","Retry the generation request — transient upstream failures can yield empty payloads","Upgrade SiYuan in case the adapter's response parsing was fixed for a changed API format"],"exampleFix":"// before: decoding whatever the API returned\nimgData, _ := base64.StdEncoding.DecodeString(resp.Data[0].B64JSON)\nif err := ValidateGeneratedImage(imgData); err != nil { ... }\n// after: guard the empty payload at the source\nif resp.Data[0].B64JSON == \"\" {\n    return errors.New(\"model returned no image data\")\n}\nimgData, _ := base64.StdEncoding.DecodeString(resp.Data[0].B64JSON)\nif err := ValidateGeneratedImage(imgData); err != nil { ... }","handlingStrategy":"validation","validationCode":"if b64 == \"\" { return errors.New(\"model returned no image data\") }\nimgData, err := base64.StdEncoding.DecodeString(b64)\nif err != nil { return err }\nif len(imgData) == 0 { return errors.New(\"decoded image payload is empty\") }","typeGuard":null,"tryCatchPattern":"mime, ext, err := util.ValidateGeneratedImage(data)\nif err != nil && err.Error() == \"generated image is empty\" {\n    // treat as transient upstream failure; retry the generation once\n    return retryGeneration()\n}","preventionTips":["Check the b64_json/URL field for emptiness before decoding","Verify HTTP status and response shape before extracting image bytes","Log the raw response when generation succeeds but yields no bytes","Retry once on empty payloads — upstream blips are a common cause"],"tags":["image","ai","empty-payload","validation"],"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"}