siyuan-note/siyuan · error
generated image is empty
Error message
generated image is empty
What it means
Thrown by ValidateGeneratedImage (kernel/util/openai.go:698) when the byte slice passed in has length 0. It is the first guard in the AI-generated image validation pipeline and exists because downstream MIME detection (mimetype.Detect) and image.DecodeConfig both misbehave or panic-prone on empty input. SiYuan runs it on every image returned by an OpenAIImageAdapter before persisting it.
Source
Thrown at kernel/util/openai.go:698
if err = jpeg.Encode(&output, decoded, &jpeg.Options{Quality: 92}); err != nil {
return PreparedImage{}, errors.New("encode image failed: " + err.Error())
}
if maxBytes > 0 && output.Len() > maxBytes {
return PreparedImage{}, fmt.Errorf("prepared image exceeds size limit: %d bytes", maxBytes)
}
return PreparedImage{
Data: output.Bytes(),
MIMEType: "image/jpeg",
Width: bounds.Dx(),
Height: bounds.Dy(),
SourceSize: len(data),
}, nil
}
// ValidateGeneratedImage 校验生成图片的格式、尺寸和体积。
func ValidateGeneratedImage(data []byte) (mimeType, extension string, err error) {
if len(data) == 0 {
return "", "", errors.New("generated image is empty")
}
if len(data) > maxGeneratedImageBytes {
return "", "", errors.New("generated image exceeds size limit")
}
mimeType = mimetype.Detect(data).String()
switch mimeType {
case "image/png":
extension = ".png"
case "image/jpeg":
extension = ".jpg"
case "image/webp":
extension = ".webp"
default:
return "", "", fmt.Errorf("unsupported generated image type: %s", mimeType)
}
config, _, decodeErr := image.DecodeConfig(bytes.NewReader(data))
if decodeErr != nil || config.Width < 1 || config.Height < 1 || config.Width > 16384 || config.Height > 16384 ||
int64(config.Width)*int64(config.Height) > maxGeneratedImagePixels {View on GitHub (pinned to 251596fc0d)
Solutions
- Inspect the upstream model response: log result.B64JSON length and the HTTP status / Content-Length of the downloaded URL to find where the bytes were lost.
- Guard the call site: only invoke ValidateGeneratedImage when len(data) > 0, otherwise short-circuit with a clearer upstream error.
- If using URL mode, retry the download once — empty bodies from signed CDN URLs are often transient.
- Verify the openai-go client and model endpoint actually populate response.Data[0].B64JSON / .URL.
Example fix
// before
data, err := base64.StdEncoding.DecodeString(result.B64JSON)
if err != nil { return GeneratedImage{}, err }
mimeType, ext, err := ValidateGeneratedImage(data)
// after
data, err := base64.StdEncoding.DecodeString(result.B64JSON)
if err != nil { return GeneratedImage{}, err }
if len(data) == 0 {
return GeneratedImage{}, fmt.Errorf("model %s returned empty image payload", adapter.model)
}
mimeType, ext, err := ValidateGeneratedImage(data) Defensive patterns
Strategy: validation
Validate before calling
// Run before ValidateGeneratedImage to short-circuit empty payloads
func hasImageBytes(data []byte) bool { return len(data) > 0 }
// usage
if !hasImageBytes(data) {
return GeneratedImage{}, errors.New("upstream model returned no image bytes")
}
mimeType, ext, err := ValidateGeneratedImage(data) Try / catch
mimeType, ext, err := ValidateGeneratedImage(data)
if err != nil {
// err may be "generated image is empty"; log len(data) for diagnosis
logging.LogWarnf("validate generated image failed: %s (len=%d)", err, len(data))
return err
} Prevention
- Always check len(data) > 0 immediately after base64-decoding or downloading image bytes.
- Log the length of result.B64JSON and the HTTP status/Content-Length of any URL response before validation.
- When wiring a new image provider, write a contract test that asserts a non-empty payload on a fixed prompt.
When it happens
Trigger: Calling ValidateGeneratedImage([]byte{}) directly; or OpenAIImageAdapter.Generate receiving a result whose B64JSON decoded to zero bytes, or whose URL returned HTTP 200 with an empty body. Also reachable if a caller wraps an upstream API whose 'data' field is present but empty.
Common situations: The model's response was filtered/empty but still returned 200 OK; a transient CDN issue served a 0-byte body; a base64 string decoded cleanly to nothing (e.g. provider sent ""); an integration bug truncated the byte buffer before validation.
Related errors
- generated image exceeds size limit
- unsupported generated image type: %s
- generated image is invalid
- image prompt is required
- image model returned no image
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/b46d2dd778f1fcd8.
Report an issue: GitHub.