siyuan-note/siyuan · error

unsupported generated image type

Error message

unsupported generated image type: %s

What it means

ValidateGeneratedImage in kernel/util/openai.go throws this when mimetype.Detect classifies the generated bytes as something other than image/png, image/jpeg, or image/webp. The detected MIME string is interpolated into the message, so it usually reveals what was actually received (e.g. text/html or application/json).

Solutions

  1. Read the detected type in the message — if it is text/html or application/json, inspect that body for the real API error (auth, quota, invalid request)
  2. Confirm the model/endpoint actually returns png/jpeg/webp and switch the output_format setting if it defaults to another format
  3. Re-check the API key and request parameters; error payloads often masquerade as image data
  4. Capture the response body and retry after fixing the request

Example fix

// before: validating error bodies as images
imgData, _ := io.ReadAll(httpResp.Body)
mime, ext, err := ValidateGeneratedImage(imgData)
// after: check HTTP status before treating body as an image
if httpResp.StatusCode != 200 {
    return fmt.Errorf("image API error: %s", httpResp.Status)
}
imgData, _ := io.ReadAll(httpResp.Body)
mime, ext, err := ValidateGeneratedImage(imgData)
Defensive patterns

Strategy: validation

Validate before calling

head, _ := io.ReadAll(io.LimitReader(r, 512))
kind := mimetype.Detect(head).String()
if kind != "image/png" && kind != "image/jpeg" && kind != "image/webp" {
    return fmt.Errorf("expected image, got %s — inspect body for API error", kind)
}

Try / catch

mime, ext, err := util.ValidateGeneratedImage(data)
if err != nil && strings.HasPrefix(err.Error(), "unsupported generated image type:") {
    // dump the first bytes — likely an HTML/JSON error payload
    log.Printf("payload head: %q", data[:min(256, len(data))])
    return err
}

Prevention

When it happens

Trigger: The byte payload from the image API has magic bytes that do not match png/jpeg/webp — most commonly an HTML error page, a JSON error envelope, or SVG/HEIC/AVIF output stored as bytes.

Common situations: The API returned an error page instead of an image (auth failure, rate limit) and the caller passed the body straight to validation; the provider switched to an unsupported format (AVIF/SVG); a download URL redirected to an HTML login page.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/996640cad064227b. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/openai.go:852

// 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 {
		return "", "", errors.New("generated image is invalid")
	}
	return mimeType, extension, nil
}

func NewOpenAIImageAdapter(apiKey, apiBaseURL, model string, timeout int, headers ...map[string]string) *OpenAIImageAdapter {
	if timeout < 1 {
		timeout = 30
	}
	client := NewOpenAIClientWithModel(apiKey, apiBaseURL, model, headers...)
	if isMiniMaxImageEndpoint(apiBaseURL) {
		config := openai.DefaultConfig(apiKey)
		config.BaseURL = apiBaseURL
		config.HTTPClient = &miniMaxImageTransport{base: newAIProviderHTTPClient(apiBaseURL, headers...)}

View on GitHub (pinned to 9f775e8a12)