siyuan-note/siyuan · error

unsupported image type

Error message

unsupported image type: %s

What it means

PrepareModelImage accepts only image/gif, image/jpeg, image/png, and image/webp as detected MIME types; any other detected type (BMP, TIFF, HEIC, AVIF, PDF, text, etc.) yields this error naming the detected MIME type. These four formats are what mainstream multimodal APIs accept, so everything else is rejected before decoding.

Solutions

  1. Convert the image to PNG, JPEG, or WebP before attaching (any image converter or 'open in editor, save as PNG')
  2. For HEIC photos, convert to JPEG during import or via the OS image pipeline
  3. Verify the file is actually an image — the MIME type in the error reveals the true content type
  4. If inserting via automation, normalize all assets to PNG/JPEG as a preprocessing step

Example fix

// before
prepared, err := PrepareModelImage(heicBytes, maxBytes, maxPixels, maxEdge) // "unsupported image type: image/heic"
// after
jpegBytes := convert(heicBytes, "image/jpeg") // transcode HEIC to JPEG first
prepared, err := PrepareModelImage(jpegBytes, maxBytes, maxPixels, maxEdge)
Defensive patterns

Strategy: validation

Validate before calling

mt := mimetype.Detect(data).String()
if !isRasterImage(mt) { data = transcodeToJPEG(data) }

Type guard

func isRasterImage(mt string) bool {
    switch mt {
    case "image/gif", "image/jpeg", "image/png", "image/webp":
        return true
    }
    return false
}

Try / catch

prepared, err := PrepareModelImage(data, maxBytes, maxPixels, maxEdge)
if err != nil && strings.Contains(err.Error(), "unsupported image type") {
    prepared, err = PrepareModelImage(transcodeToJPEG(data), maxBytes, maxPixels, maxEdge)
}

Prevention

When it happens

Trigger: Calling PrepareModelImage on data whose mimetype.Detect result is not one of the four supported types — e.g. attaching a .bmp screenshot, an iPhone .heic photo, a TIFF scan, or accidentally a non-image file.

Common situations: iOS/macOS HEIC photos copied straight into SiYuan; Windows BMP screenshots from legacy tools; TIFF scans from scanners; an asset file that is actually a document or text file misnamed with an image extension.

Related errors


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

Appendix: source

Thrown at kernel/util/openai.go:775

	return
}

// PrepareModelImage 校验并按需缩放图片,尽量保留多模态模型支持的原始格式和图片质量。
func PrepareModelImage(data []byte, maxBytes, maxPixels, maxEdge int) (PreparedImage, error) {
	if len(data) == 0 {
		return PreparedImage{}, errors.New("image data is empty")
	}
	if maxBytes > 0 && len(data) > maxBytes {
		return PreparedImage{}, fmt.Errorf("image exceeds size limit: %d bytes", maxBytes)
	}
	mimeType := mimetype.Detect(data).String()
	if strings.Contains(mimeType, "svg") || bytes.Contains(bytes.ToLower(data[:min(len(data), 512)]), []byte("<svg")) {
		return PreparedImage{}, errors.New("SVG images are not accepted by multimodal models")
	}
	switch mimeType {
	case "image/gif", "image/jpeg", "image/png", "image/webp":
	default:
		return PreparedImage{}, fmt.Errorf("unsupported image type: %s", mimeType)
	}
	config, _, err := image.DecodeConfig(bytes.NewReader(data))
	if err != nil {
		return PreparedImage{}, errors.New("unsupported or invalid image: " + err.Error())
	}
	if config.Width < 1 || config.Height < 1 || maxPixels > 0 && int64(config.Width)*int64(config.Height) > int64(maxPixels) {
		return PreparedImage{}, fmt.Errorf("image exceeds pixel limit: %d", maxPixels)
	}

	decoded, err := imaging.Decode(bytes.NewReader(data), imaging.AutoOrientation(true))
	if err != nil {
		return PreparedImage{}, errors.New("decode image failed: " + err.Error())
	}
	bounds := decoded.Bounds()
	needsResize := maxEdge > 0 && (bounds.Dx() > maxEdge || bounds.Dy() > maxEdge)
	if !needsResize && bounds.Dx() == config.Width && bounds.Dy() == config.Height && mimeType != "image/gif" {
		return PreparedImage{
			Data:       data,

View on GitHub (pinned to 9f775e8a12)