siyuan-note/siyuan · error
generated image is invalid
Error message
generated image is invalid
What it means
Thrown by ValidateGeneratedImage (kernel/util/openai.go:717) after the MIME check passes but image.DecodeConfig fails, or the decoded dimensions are out of bounds: width/height must be 1..16384 and width*height must not exceed maxGeneratedImagePixels (100 * 1000 * 1000, ~100MP). It catches corrupt, truncated, or absurdly large images that nonetheless sniff as a valid PNG/JPEG/WebP.
Source
Thrown at kernel/util/openai.go:717
}
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 {
return "", "", errors.New("generated image is invalid")
}
return mimeType, extension, nil
}
func NewOpenAIImageAdapter(apiKey, apiBaseURL, model string, timeout int) *OpenAIImageAdapter {
if timeout < 1 {
timeout = 30
}
return &OpenAIImageAdapter{
client: NewOpenAIClientWithModel(apiKey, apiBaseURL, model),
model: model,
timeout: time.Duration(timeout) * time.Second,
}
}
func (adapter *OpenAIImageAdapter) Generate(ctx context.Context, request GenerateImageRequest) (GeneratedImage, error) {
if strings.TrimSpace(request.Prompt) == "" {
return GeneratedImage{}, errors.New("image prompt is required")View on GitHub (pinned to 251596fc0d)
Solutions
- Re-fetch or regenerate the image — corrupt payloads from signed CDN URLs are often transient.
- If persistently failing, capture the bytes and run `file -k` / `identify` locally to confirm the header is well-formed.
- Verify the model's configured Size does not exceed 16384 on either dimension.
- If you control the source, ensure the encoder flushes the full file before returning.
Example fix
// before
data, err := downloadGeneratedImage(requestCtx, result.URL)
if err != nil { return GeneratedImage{}, err }
mimeType, extension, err := ValidateGeneratedImage(data)
// after (retry once on decode-class failures)
data, err := downloadGeneratedImage(requestCtx, result.URL)
if err != nil { return GeneratedImage{}, err }
if _, _, verr := ValidateGeneratedImage(data); verr != nil {
logging.LogWarnf("generated image invalid, retrying once: %s", verr)
data, err = downloadGeneratedImage(requestCtx, result.URL)
if err != nil { return GeneratedImage{}, err }
}
mimeType, extension, err := ValidateGeneratedImage(data) Defensive patterns
Strategy: retry
Validate before calling
// Cheap pre-check: decode config yourself first, with a clearer failure path
cfg, _, derr := image.DecodeConfig(bytes.NewReader(data))
if derr != nil {
return fmt.Errorf("image header undecodable (truncated?): %s", derr)
}
if cfg.Width < 1 || cfg.Height < 1 || cfg.Width > 16384 || cfg.Height > 16384 ||
int64(cfg.Width)*int64(cfg.Height) > 100_000_000 {
return errors.New("image dimensions out of accepted range")
} Try / catch
mimeType, ext, err := ValidateGeneratedImage(data)
if err != nil && err.Error() == "generated image is invalid" {
// often transient (truncated download); retry once
data, derr := downloadGeneratedImage(ctx, url)
if derr == nil {
mimeType, ext, err = ValidateGeneratedImage(data)
}
}
if err != nil { return err } Prevention
- Retry downloads once — truncated bodies from signed CDN URLs are common.
- Inspect the byte length and first bytes; a header without pixel data points to truncation.
- Ensure the requested Size never exceeds 16384 on either dimension.
When it happens
Trigger: Bytes that pass mimetype detection but are truncated so image.DecodeConfig errors; a PNG/JPEG whose declared dimensions exceed 16384 on either side; a generated image whose total pixel count exceeds 100MP; a malformed header that the MIME sniffer accepted.
Common situations: Truncated download (connection dropped mid-body); provider returned a header-only stub; adversarial 'decompression bomb' style header; provider bug emitting a tiny valid header with no pixel data.
Related errors
- generated image is empty
- generated image exceeds size limit
- unsupported generated image type: %s
- 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/d529f35f294a6d27.
Report an issue: GitHub.