spring-projects/spring-ai · error · IllegalArgumentException

Image generation failed: no image returned

Error message

Image generation failed: no image returned

What it means

OpenAiImageModel.call validates that the OpenAI images API returned a non-empty data array. When the response has no entries at all, it throws this IllegalArgumentException, since an image generation with zero results is unusable.

Solutions

  1. Inspect the prompt and options (model, size, quality, n) for combinations the API may reject silently; adjust and retry.
  2. Catch IllegalArgumentException around call() and surface a user-facing 'no image produced' message.
  3. Enable HTTP logging to inspect the raw response and confirm the API returned an empty data array.

Example fix

try {
    ImageResponse response = imageModel.call(new ImagePrompt(prompt));
}
catch (IllegalArgumentException e) {
    if (e.getMessage().contains("no image returned")) {
        throw new ImageGenerationException("Model returned no image; revise prompt or options", e);
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (promptText == null || promptText.isBlank()) {
    throw new IllegalArgumentException("Prompt must not be blank before calling image model");
}

Try / catch

try {
    ImageResponse r = imageModel.call(new ImagePrompt(prompt));
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("no image returned")) {
        throw new ImageGenerationException("API returned no images; revise prompt or options", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling OpenAiImageModel.call(...) when the API response's images.data() is empty or the Optional list is empty — e.g. the API silently returned no images for the prompt/model/parameters combination.

Common situations: Content-policy-filtered prompts, unsupported model+parameter combinations (e.g. gpt-image-1 with response_format), or a misconfigured Azure deployment returning an empty body.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/b30001e66380b069. Report an issue: GitHub.

Appendix: source

Thrown at models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageModel.java:212

		if (logger.isTraceEnabled()) {
			logger.trace("OpenAiImageOptions call " + options.getModel() + " with the following options : "
					+ imageGenerateParams);
		}

		var observationContext = ImageModelObservationContext.builder()
			.imagePrompt(imagePrompt)
			.provider(AiProvider.OPENAI.value())
			.build();

		return Objects.requireNonNull(
				ImageModelObservationDocumentation.IMAGE_MODEL_OPERATION
					.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
							this.observationRegistry)
					.observe(() -> {
						var images = this.openAiClient.images().generate(imageGenerateParams, requestOptions);

						if (images.data().isEmpty() || images.data().get().isEmpty()) {
							throw new IllegalArgumentException("Image generation failed: no image returned");
						}

						List<ImageGeneration> imageGenerations = images.data().get().stream().map(nativeImage -> {
							Image image;
							if (nativeImage.url().isPresent()) {
								image = new Image(nativeImage.url().get(), null);
							}
							else if (nativeImage.b64Json().isPresent()) {
								image = new Image(null, nativeImage.b64Json().get());
							}
							else {
								throw new IllegalArgumentException(
										"Image generation failed: image entry missing url and b64_json");
							}
							var metadata = new OpenAiImageGenerationMetadata(nativeImage.revisedPrompt().orElse(null));
							return new ImageGeneration(image, metadata);
						}).toList();
						ImageResponseMetadata openAiImageResponseMetadata = OpenAiImageResponseMetadata.from(images);

View on GitHub (pinned to 98a7beda4f)