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

  1. 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.
  2. Guard the call site: only invoke ValidateGeneratedImage when len(data) > 0, otherwise short-circuit with a clearer upstream error.
  3. If using URL mode, retry the download once — empty bodies from signed CDN URLs are often transient.
  4. 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

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


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/b46d2dd778f1fcd8. Report an issue: GitHub.