{"record":{"id":"b012a3235e75a1c8","repo":"siyuan-note/siyuan","slug":"image-model-returned-neither-base64-data-nor-url","errorCode":null,"errorMessage":"image model returned neither base64 data nor URL","messagePattern":"image model returned neither base64 data nor URL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai.go","lineNumber":768,"sourceCode":"\t\timageRequest.OutputFormat = request.OutputFormat\n\t}\n\trequestCtx, cancel := context.WithTimeout(ctx, adapter.timeout)\n\tdefer cancel()\n\tresponse, err := adapter.client.CreateImage(requestCtx, imageRequest)\n\tif err != nil {\n\t\treturn GeneratedImage{}, err\n\t}\n\tif len(response.Data) == 0 {\n\t\treturn GeneratedImage{}, errors.New(\"image model returned no image\")\n\t}\n\tresult := response.Data[0]\n\tvar data []byte\n\tif result.B64JSON != \"\" {\n\t\tdata, err = base64.StdEncoding.DecodeString(result.B64JSON)\n\t} else if result.URL != \"\" {\n\t\tdata, err = downloadGeneratedImage(requestCtx, result.URL)\n\t} else {\n\t\terr = errors.New(\"image model returned neither base64 data nor URL\")\n\t}\n\tif err != nil {\n\t\treturn GeneratedImage{}, err\n\t}\n\tmimeType, extension, err := ValidateGeneratedImage(data)\n\tif err != nil {\n\t\treturn GeneratedImage{}, err\n\t}\n\treturn GeneratedImage{Data: data, MIMEType: mimeType, Extension: extension, RevisedPrompt: result.RevisedPrompt}, nil\n}\n\nfunc downloadGeneratedImage(ctx context.Context, rawURL string) ([]byte, error) {\n\tparsed, err := url.Parse(rawURL)\n\tif err != nil || parsed.Scheme != \"https\" || parsed.Host == \"\" {\n\t\treturn nil, errors.New(\"generated image URL must use HTTPS\")\n\t}\n\tif err = CheckHostSSRF(parsed.Hostname()); err != nil {\n\t\treturn nil, err","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/util/openai.go#L750-L786","documentation":"Thrown by OpenAIImageAdapter.Generate (kernel/util/openai.go:768) when response.Data has at least one element but its first element has neither B64JSON nor a URL. SiYuan requires exactly one of these transport modes; absence of both means the provider's response item schema does not match the openai-go client's expectations.","triggerScenarios":"Provider returns a data item with only a revised_prompt field and no payload; provider uses a non-standard field name (e.g. b64_json vs b64Json casing mismatch); openai-go client version out of sync with provider schema.","commonSituations":"OpenAI-compatible third-party endpoint with a different response envelope; client/server version mismatch after a provider API update; content-policy rejection that returns a stub item with neither field.","solutions":["Update the openai-go client to a version matching the provider's current image API schema.","Dump response.Data[0] (marshalled JSON) to see which fields the provider actually populates.","If the provider uses a different field name, switch to a compatible adapter or normalize the response.","Retry once in case the item was a transient stub."],"exampleFix":"// before\nif result.B64JSON != \"\" {\n    data, err = base64.StdEncoding.DecodeString(result.B64JSON)\n} else if result.URL != \"\" {\n    data, err = downloadGeneratedImage(requestCtx, result.URL)\n} else {\n    err = errors.New(\"image model returned neither base64 data nor URL\")\n}\n\n// after (surface provider payload for diagnosis)\nif result.B64JSON != \"\" {\n    data, err = base64.StdEncoding.DecodeString(result.B64JSON)\n} else if result.URL != \"\" {\n    data, err = downloadGeneratedImage(requestCtx, result.URL)\n} else {\n    raw, _ := json.Marshal(result)\n    err = fmt.Errorf(\"image model returned neither base64 data nor URL; item=%s\", raw)\n}","handlingStrategy":"validation","validationCode":"// Inspect the item fields before dispatching to decode/download\nresult := response.Data[0]\nif result.B64JSON == \"\" && result.URL == \"\" {\n    raw, _ := json.Marshal(result)\n    return fmt.Errorf(\"provider item has no b64/URL; item=%s\", raw)\n}","typeGuard":null,"tryCatchPattern":"if result.B64JSON != \"\" {\n    data, err = base64.StdEncoding.DecodeString(result.B64JSON)\n} else if result.URL != \"\" {\n    data, err = downloadGeneratedImage(ctx, result.URL)\n} else {\n    // schema drift: dump the item, retry once, then escalate\n    raw, _ := json.Marshal(result)\n    logging.LogErrorf(\"unexpected image item shape: %s\", raw)\n    err = fmt.Errorf(\"image model returned neither base64 data nor URL\")\n}","preventionTips":["Pin or upgrade the openai-go client to match the provider's image API version.","Add an integration test that asserts at least one of B64JSON/URL is populated.","For OpenAI-compatible shims, document which response field they populate."],"tags":["openai","image-generation","provider","schema","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}