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
- Check the returned ChatResponse.getResults() for emptiness before calling .get(0) or joining text
- Increase max_tokens in AnthropicChatOptions and remove/review stop_sequence settings
- Inspect the raw HTTP response (enable logging) to see why Anthropic returned no content
- Upgrade the spring-ai-anthropic SDK/dependency to the latest version to pick up content-block mapping fixes
- 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
- Always null/empty-check ChatResponse.getResults() before accessing getResult()
- Set a reasonable max_tokens (not 0/tiny) in AnthropicChatOptions
- Review stop_sequence configuration so it cannot fire before any output
- Enable HTTP logging when debugging to inspect raw Anthropic responses
- Keep the anthropic SDK dependency current for content-mapping fixes
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
- Unsupported media type: . Supported types are: images (image
- Unsupported media data type: . Expected byte[] or String.
- Unsupported image type: . Supported types: image/png, image/
- httpClientBuilderCustomizers cannot be combined with a pre-b
- httpClientBuilderCustomizers cannot be combined with a pre-b
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/b3478e9ad8ce7f2a.
Report an issue: GitHub.