{"record":{"id":"996640cad064227b","repo":"siyuan-note/siyuan","slug":"unsupported-generated-image-type-s","errorCode":null,"errorMessage":"unsupported generated image type: %s","messagePattern":"unsupported generated image type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai.go","lineNumber":712,"sourceCode":"\n// ValidateGeneratedImage 校验生成图片的格式、尺寸和体积。\nfunc ValidateGeneratedImage(data []byte) (mimeType, extension string, err error) {\n\tif len(data) == 0 {\n\t\treturn \"\", \"\", errors.New(\"generated image is empty\")\n\t}\n\tif len(data) > maxGeneratedImageBytes {\n\t\treturn \"\", \"\", errors.New(\"generated image exceeds size limit\")\n\t}\n\tmimeType = mimetype.Detect(data).String()\n\tswitch mimeType {\n\tcase \"image/png\":\n\t\textension = \".png\"\n\tcase \"image/jpeg\":\n\t\textension = \".jpg\"\n\tcase \"image/webp\":\n\t\textension = \".webp\"\n\tdefault:\n\t\treturn \"\", \"\", fmt.Errorf(\"unsupported generated image type: %s\", mimeType)\n\t}\n\tconfig, _, decodeErr := image.DecodeConfig(bytes.NewReader(data))\n\tif decodeErr != nil || config.Width < 1 || config.Height < 1 || config.Width > 16384 || config.Height > 16384 ||\n\t\tint64(config.Width)*int64(config.Height) > maxGeneratedImagePixels {\n\t\treturn \"\", \"\", errors.New(\"generated image is invalid\")\n\t}\n\treturn mimeType, extension, nil\n}\n\nfunc NewOpenAIImageAdapter(apiKey, apiBaseURL, model string, timeout int) *OpenAIImageAdapter {\n\tif timeout < 1 {\n\t\ttimeout = 30\n\t}\n\treturn &OpenAIImageAdapter{\n\t\tclient:  NewOpenAIClientWithModel(apiKey, apiBaseURL, model),\n\t\tmodel:   model,\n\t\ttimeout: time.Duration(timeout) * time.Second,\n\t}","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/util/openai.go#L694-L730","documentation":"Thrown by ValidateGeneratedImage (kernel/util/openai.go:712) when mimetype.Detect reports a MIME type that is not image/png, image/jpeg, or image/webp. SiYuan only persists those three formats for generated images; anything else (GIF, AVIF, HEIC, BMP, or non-image content) is rejected before dimension validation.","triggerScenarios":"Provider returns bytes whose magic bytes sniff as GIF/BMP/TIFF/AVIF/HEIC; or returns an HTML/JSON error body that mimetype classifies as text/html or application/json; or returns a corrupted buffer whose leading bytes match a non-image signature.","commonSituations":"Model misconfigured to emit unsupported format; API key invalid and provider returned an HTML error page captured as the 'image'; partial download whose first bytes coincidentally sniff as a non-image type; new model outputting AVIF before SiYuan whitelisted it.","solutions":["Log the detected mimeType string to identify what the provider actually returned.","If you control the request, force OutputFormat/ResponseFormat to png/jpeg/webp on the GenerateImageRequest.","If extending support is intended, add the new MIME case to the switch and a matching decoder registration for image.DecodeConfig.","If the body is an error page (HTML/JSON), the upstream call failed silently — check API key, quota, and provider status."],"exampleFix":"// before\nmimeType = mimetype.Detect(data).String()\nswitch mimeType {\ncase \"image/png\":  extension = \".png\"\ncase \"image/jpeg\": extension = \".jpg\"\ncase \"image/webp\": extension = \".webp\"\ndefault:\n    return \"\", \"\", fmt.Errorf(\"unsupported generated image type: %s\", mimeType)\n}\n\n// after (extend support + clearer rejection)\nmimeType = mimetype.Detect(data).String()\nswitch mimeType {\ncase \"image/png\":  extension = \".png\"\ncase \"image/jpeg\": extension = \".jpg\"\ncase \"image/webp\": extension = \".webp\"\ncase \"image/avif\": extension = \".avif\"\ndefault:\n    return \"\", \"\", fmt.Errorf(\"unsupported generated image type %q (first bytes: % x)\", mimeType, data[:min(16, len(data))])\n}","handlingStrategy":"validation","validationCode":"// Detect the MIME type the same way ValidateGeneratedImage does, then allow-list\nallowed := map[string]bool{\"image/png\": true, \"image/jpeg\": true, \"image/webp\": true}\nmt := mimetype.Detect(data).String()\nif !allowed[mt] {\n    return fmt.Errorf(\"pre-check: provider returned %s, not png/jpeg/webp\", mt)\n}","typeGuard":null,"tryCatchPattern":"mimeType, ext, err := ValidateGeneratedImage(data)\nif err != nil && strings.HasPrefix(err.Error(), \"unsupported generated image type\") {\n    // provider returned a non-whitelisted format; either extend the switch or fix upstream\n    logging.LogErrorf(\"unexpected image MIME: %s\", err)\n}\nif err != nil { return err }","preventionTips":["Force the request's OutputFormat/ResponseFormat to png/jpeg/webp when the provider supports it.","If extending support, add the MIME case AND register the decoder for image.DecodeConfig.","Verify API key/quota when the body sniffs as text/html or application/json — that's usually an error page."],"tags":["openai","image-generation","validation","mime","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}