spring-projects/spring-ai · error · java.lang.IllegalArgumentException

ImagePrompt must contain at least one non-empty message

Error message

ImagePrompt must contain at least one non-empty message

What it means

GoogleGenAiImageModel.call() converts each message in the ImagePrompt into Gemini Content objects with parts, filtering out messages that produce no parts (e.g. no text and no media). If no message yields any parts, there is no usable prompt to send to generateContent, so it throws this IllegalArgumentException.

Source

Thrown at models/spring-ai-google-genai-image/src/main/java/org/springframework/ai/google/genai/image/GoogleGenAiImageModel.java:145

				final GoogleGenAiImageOptions options = (GoogleGenAiImageOptions) imagePrompt.getOptions();
				Assert.notNull(options, "Options must not be null");

				final String model = options.getModel();
				Assert.notNull(model, "Model must not be null");

				final String modelName = this.connectionDetails.getModelEndpointName(model);

				final GenerateContentConfig config = getGenerateContentConfig(options);

				final List<Content> contents = imagePrompt.getInstructions()
					.stream()
					.map(GoogleGenAiImageModel::messageToParts)
					.filter(Predicate.not(List::isEmpty))
					.map(parts -> Content.builder().role(MessageType.USER.getValue()).parts(parts).build())
					.toList();

				if (contents.isEmpty()) {
					throw new IllegalArgumentException("ImagePrompt must contain at least one non-empty message");
				}

				final GenerateContentResponse imagesResponse = RetryUtils.execute(this.retryTemplate,
						() -> this.genAiClient.models.generateContent(modelName, contents, config));

				final List<Candidate> candidates = Optional.ofNullable(imagesResponse)
					.map(GenerateContentResponse::candidates)
					.flatMap(Function.identity())
					.orElse(List.of());

				final List<ImageGeneration> generationList = candidates.stream()
					.flatMap(GoogleGenAiImageModel::candidateToImageGenerations)
					.toList();

				final List<String> candidateTexts = candidates.stream()
					.flatMap(candidate -> candidate.content().flatMap(Content::parts).orElse(List.of()).stream())
					.filter(part -> part.inlineData().isEmpty())
					.map(Part::text)

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Validate the prompt before calling: ensure the ImagePrompt contains at least one message with non-blank text or media.
  2. Fix template/user-input handling so blank prompts are rejected or filled earlier.
  3. Wrap the call in a guard that throws a more descriptive application-level error for empty prompts.

Example fix

// before
ImageResponse res = imageModel.call(new ImagePrompt(userInput));

// after
if (!StringUtils.hasText(userInput)) {
    throw new IllegalArgumentException("Image prompt text must not be blank");
}
ImageResponse res = imageModel.call(new ImagePrompt(userInput));
Defensive patterns

Strategy: validation

Validate before calling

boolean hasPrompt = prompt.getInstructions().stream()
    .anyMatch(m -> StringUtils.hasText(m.getText()) || (m.getMedia() != null && !m.getMedia().isEmpty()));
if (!hasPrompt) { throw new IllegalArgumentException("ImagePrompt is empty"); }

Prevention

When it happens

Trigger: Calling call(new ImagePrompt("")) or an ImagePrompt whose messages contain only empty strings / blank instructions — every message maps to an empty parts list and 'contents' ends up empty.

Common situations: Template-rendered prompts that resolved to an empty string (missing template variables); user input passed through unvalidated and blank; a refactor passing instructions as empty lists; whitespace-only prompts from form submissions.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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