spring-projects/spring-ai · warning

No content blocks returned for prompt: + prompt

Error message

No content blocks returned for prompt: + prompt

What it means

A warning logged by AnthropicChatModel.internalCall when the Anthropic API returned a successful response whose message contains an empty content blocks list. The model returns an empty ChatResponse (List.of()) instead of throwing, so callers receive a response with no generations. This typically means the model produced no output (e.g. it was stopped, filtered, or the request was malformed in a way the API accepted but answered vacuously).

Source

Thrown at models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java:568

			.prompt(prompt)
			.provider(AiProvider.ANTHROPIC.value())
			.build();

		ChatResponse response = ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
			.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
					this.observationRegistry)
			.observe(() -> {

				HttpResponseFor<Message> rawResponse = this.anthropicClient.messages()
					.withRawResponse()
					.create(request, requestOptionsFor(prompt));
				Message message = rawResponse.parse();
				RateLimit rateLimit = AnthropicRateLimit.from(rawResponse.headers());

				List<ContentBlock> contentBlocks = message.content();
				if (contentBlocks.isEmpty()) {
					if (logger.isWarnEnabled()) {
						logger.warn("No content blocks returned for prompt: " + prompt);
					}
					return new ChatResponse(List.of());
				}

				List<Citation> citations = new ArrayList<>();
				List<AnthropicWebSearchResult> webSearchResults = new ArrayList<>();
				List<Generation> generations = buildGenerations(message, citations, webSearchResults);

				// Current usage
				com.anthropic.models.messages.Usage sdkUsage = message.usage();
				Usage currentChatResponseUsage = getDefaultUsage(sdkUsage);
				Usage accumulatedUsage = previousChatResponse != null
						? UsageCalculator.getCumulativeUsage(currentChatResponseUsage, previousChatResponse)
						: currentChatResponseUsage;

				ChatResponse chatResponse = new ChatResponse(generations,
						from(message, accumulatedUsage, citations, webSearchResults, rateLimit));

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Check the returned ChatResponse.getResults() for emptiness before calling .get(0) or joining text
  2. Increase max_tokens in AnthropicChatOptions and remove/review stop_sequence settings
  3. Inspect the raw HTTP response (enable logging) to see why Anthropic returned no content
  4. Upgrade the spring-ai-anthropic SDK/dependency to the latest version to pick up content-block mapping fixes
  5. Retry the request; a transient API issue can produce empty bodies

Example fix

// before
ChatResponse response = chatModel.call(new Prompt("hi"));
String text = response.getResult().getOutput().getText(); // NPE/ISE on empty
// after
ChatResponse response = chatModel.call(new Prompt("hi"));
if (response == null || response.getResults().isEmpty()) {
    logger.warn("Anthropic returned no content");
    return fallbackAnswer;
}
String text = response.getResult().getOutput().getText();
Defensive patterns

Strategy: fallback

Validate before calling

// before calling, sanity-check options
if (options.getMaxTokens() == null || options.getMaxTokens() <= 0) {
    throw new IllegalArgumentException("max_tokens must be positive");
}

Type guard

boolean hasContent(ChatResponse r) {
    return r != null && r.getResults() != null && !r.getResults().isEmpty()
        && r.getResult().getOutput() != null;
}

Try / catch

ChatResponse resp = chatModel.call(new Prompt(prompt, options));
if (resp == null || CollectionUtils.isEmpty(resp.getResults())) {
    logger.warn("Empty Anthropic response; using fallback");
    return fallbackResponse;
}

Prevention

When it happens

Trigger: Calling AnthropicChatModel.call()/internalCall where rawResponse.parse() yields a Message whose content() list is empty — e.g. max_tokens set so low the model emitted nothing, a stop_sequence hit immediately, or an API contract change returning no blocks.

Common situations: max_tokens configured to 0 or a tiny value; aggressive stop sequences that trigger before any token; proxy/gateway stripping content; Anthropic API behavior changes or new block types the SDK maps to nothing; prompt refuses and returns empty under certain tool_choice settings.

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/b3478e9ad8ce7f2a. Report an issue: GitHub.