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

Failed to generate content

Error message

Failed to generate content

What it means

internalStream wraps any exception occurring while setting up or starting the streaming generateContent call into RuntimeException("Failed to generate content", e). It signals that the streaming request to the Gemini API could not be created or initiated.

Source

Thrown at models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/GoogleGenAiChatModel.java:515

							toChatResponseMetadata(cumulativeUsage, response.modelVersion().get()));
					return Flux.just(chatResponse);
				});

				AtomicReference<ChatResponse> aggregatedResponseRef = new AtomicReference<>();

				Flux<ChatResponse> aggregatedFlux = new MessageAggregator().aggregate(chatResponseFlux,
						aggregatedResponse -> {
							aggregatedResponseRef.set(aggregatedResponse);
							observationContext.setResponse(aggregatedResponse);
						});

				return aggregatedFlux.doOnError(observation::error)
					.doFinally(s -> observation.stop())
					.contextWrite(ctx -> ctx.put(ObservationThreadLocalAccessor.KEY, observation));

			}
			catch (Exception e) {
				throw new RuntimeException("Failed to generate content", e);
			}

		});
	}

	protected List<Generation> responseCandidateToGeneration(Candidate candidate) {

		// TODO - The candidateIndex (e.g. choice must be assigned to the generation).
		int candidateIndex = candidate.index().orElse(0);
		FinishReason candidateFinishReason = candidate.finishReason().orElse(new FinishReason(FinishReason.Known.STOP));

		Map<String, Object> messageMetadata = new HashMap<>();
		messageMetadata.put("candidateIndex", candidateIndex);
		messageMetadata.put("finishReason", candidateFinishReason);

		// Extract thought signatures from response parts if present
		if (candidate.content().isPresent() && candidate.content().get().parts().isPresent()) {
			List<Part> parts = candidate.content().get().parts().get();

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Read the cause (getCause()) for the underlying genai SDK error.
  2. Verify the model name and request options (temperature, safety settings, thinking config) are valid for that model.
  3. Check API key/credentials and region configuration.
  4. Ensure prompt media parts reference readable resources with detectable MIME types.

Example fix

// before
flux = chatModel.stream(new Prompt("hello")); // throws "Failed to generate content"
// after
try {
    flux = chatModel.stream(new Prompt("hello"));
} catch (RuntimeException e) {
    logger.error("stream failed", e.getCause());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before streaming, validate options
Assert.hasText(options.getModel(), "model must be set");

Try / catch

try { chatModel.stream(prompt).subscribe(...) } catch (RuntimeException e) { handleCause(e.getCause()); }

Prevention

When it happens

Trigger: Calling ChatModel.stream(prompt) when the underlying client.createContent / generateContentStream setup throws: invalid request configuration, client initialization failure, missing model, or errors from the genai SDK during streaming setup.

Common situations: Invalid model name in options; malformed contents/config built from the prompt; the genai client failing to authenticate or build the streaming call; SDK version mismatches.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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