siyuan-note/siyuan · error
image model returned neither base64 data nor URL
Error message
image model returned neither base64 data nor URL
What it means
Each item in the image API response is expected to carry either B64JSON (base64-encoded image) or URL (a link to download from). If an item has neither, the adapter cannot obtain image bytes and returns this error instead of producing an empty GeneratedImage. This usually means the provider's response shape changed or a middleware mangled it.
Solutions
- Log the raw response JSON to see what fields the provider actually returned
- Upgrade github.com/siyuan-note/httpclient/openai (go-sash) client library to one that understands the provider's response format
- If using a proxy, configure it to pass through b64_json or url fields unchanged
- Pin to a provider/API version whose items always include b64_json or url
Example fix
// before
result := response.Data[0] // B64JSON and URL both empty -> error
// after
result := response.Data[0]
if result.B64JSON == "" && result.URL == "" {
return GeneratedImage{}, fmt.Errorf("image item missing b64_json/url; raw: %s", rawBody)
} Defensive patterns
Strategy: type-guard
Validate before calling
if item.B64JSON == "" && item.URL == "" {
return errors.New("image item lacks both b64_json and url")
} Type guard
func hasImagePayload(item openai.ImageResponseDataInner) bool {
return item.B64JSON != "" || item.URL != ""
} Prevention
- Keep the OpenAI client library in sync with the provider's API version
- Log raw response bodies when adding new providers/proxies
- Prefer providers that always return b64_json for deterministic handling
When it happens
Trigger: response.Data[0] has both B64JSON == "" and URL == "" — e.g. provider returns a new field format (partial image data, streaming chunks), or a proxy rewrites the JSON dropping those fields.
Common situations: Using a third-party OpenAI-compatible proxy that returns its own response schema; provider API upgrade (gpt-image-1 style responses) with an outdated client library; response item containing only revised_prompt or error details inside Data.
Related errors
- image model returned no image
- image prompt is required
- response compaction returned no output
- generate image failed
- image model is not configured
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b012a3235e75a1c8.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/openai.go:915
imageRequest.OutputFormat = request.OutputFormat
}
requestCtx, cancel := context.WithTimeout(ctx, adapter.timeout)
defer cancel()
response, err := adapter.client.CreateImage(requestCtx, imageRequest)
if err != nil {
return GeneratedImage{}, err
}
if len(response.Data) == 0 {
return GeneratedImage{}, errors.New("image model returned no image")
}
result := response.Data[0]
var data []byte
if result.B64JSON != "" {
data, err = base64.StdEncoding.DecodeString(result.B64JSON)
} else if result.URL != "" {
data, err = downloadGeneratedImage(requestCtx, result.URL)
} else {
err = errors.New("image model returned neither base64 data nor URL")
}
if err != nil {
return GeneratedImage{}, err
}
mimeType, extension, err := ValidateGeneratedImage(data)
if err != nil {
return GeneratedImage{}, err
}
return GeneratedImage{Data: data, MIMEType: mimeType, Extension: extension, RevisedPrompt: result.RevisedPrompt}, nil
}
func downloadGeneratedImage(ctx context.Context, rawURL string) ([]byte, error) {
parsed, err := url.Parse(rawURL)
if err != nil || parsed.Scheme != "https" || parsed.Host == "" {
return nil, errors.New("generated image URL must use HTTPS")
}
if err = CheckHostSSRF(parsed.Hostname()); err != nil {
return nil, errView on GitHub (pinned to 9f775e8a12)