{"record":{"id":"8c3ef7d7d20b6776","repo":"spring-projects/spring-ai","slug":"image-generation-failed-image-entry-missing-url-a","errorCode":null,"errorMessage":"Image generation failed: image entry missing url and b64_json","messagePattern":"Image generation failed: image entry missing url and b64_json","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageModel.java","lineNumber":224,"sourceCode":"\t\t\t\t\t.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,\n\t\t\t\t\t\t\tthis.observationRegistry)\n\t\t\t\t\t.observe(() -> {\n\t\t\t\t\t\tvar images = this.openAiClient.images().generate(imageGenerateParams, requestOptions);\n\n\t\t\t\t\t\tif (images.data().isEmpty() || images.data().get().isEmpty()) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"Image generation failed: no image returned\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tList<ImageGeneration> imageGenerations = images.data().get().stream().map(nativeImage -> {\n\t\t\t\t\t\t\tImage image;\n\t\t\t\t\t\t\tif (nativeImage.url().isPresent()) {\n\t\t\t\t\t\t\t\timage = new Image(nativeImage.url().get(), null);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (nativeImage.b64Json().isPresent()) {\n\t\t\t\t\t\t\t\timage = new Image(null, nativeImage.b64Json().get());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\t\t\t\"Image generation failed: image entry missing url and b64_json\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar metadata = new OpenAiImageGenerationMetadata(nativeImage.revisedPrompt().orElse(null));\n\t\t\t\t\t\t\treturn new ImageGeneration(image, metadata);\n\t\t\t\t\t\t}).toList();\n\t\t\t\t\t\tImageResponseMetadata openAiImageResponseMetadata = OpenAiImageResponseMetadata.from(images);\n\t\t\t\t\t\tImageResponse imageResponse = new ImageResponse(imageGenerations, openAiImageResponseMetadata);\n\t\t\t\t\t\tobservationContext.setResponse(imageResponse);\n\t\t\t\t\t\treturn imageResponse;\n\t\t\t\t\t}));\n\t}\n\n\t/**\n\t * Use the provided convention for reporting observation data\n\t * @param observationConvention The provided convention\n\t */\n\tpublic void setObservationConvention(ImageModelObservationConvention observationConvention) {\n\t\tAssert.notNull(observationConvention, \"observationConvention cannot be null\");","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageModel.java#L206-L242","documentation":"Each entry in an OpenAI image response must carry either a url or a b64_json payload. If a native image entry has neither, OpenAiImageModel.call throws this IllegalArgumentException instead of building an Image with null content.","triggerScenarios":"The images API returns a data entry containing only metadata (e.g. revised_prompt) with neither url nor b64_json set — observed while mapping entries in OpenAiImageModel.call at OpenAiImageModel.java:224.","commonSituations":"Streaming/partial responses, proxies or gateways stripping fields, API behavior changes for gpt-image-1 vs dall-e models, or a custom response_format the client maps incorrectly.","solutions":["Check that your options' responseFormat matches what the selected model returns (b64_json vs url) and set it explicitly.","Log the raw response body to see what fields the API actually returned; a proxy may be stripping url/b64_json.","Catch IllegalArgumentException and retry the generation, treating the response as malformed."],"exampleFix":"ImageGenerateParams params = buildParams();\nparams = params.toBuilder().responseFormat(ImageGenerateParams.ResponseFormat.B64_JSON).build();\nImageResponse response = imageModel.call(new ImagePrompt(prompt, params));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return imageModel.call(prompt);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"missing url and b64_json\")) {\n        throw new MalformedApiResponseException(\"Image entry had no url or b64_json; check response_format and proxies\", e);\n    }\n    throw e;\n}","preventionTips":["Set response_format explicitly to match the model","Verify proxies/gateways do not strip response fields","Keep the client and model versions in sync with the API"],"tags":["image-generation","missing-field","unexpected-response"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}