spring-projects/spring-ai · warning
No choices returned for prompt: + prompt
Error message
No choices returned for prompt: + prompt
What it means
Warning logged by DeepSeekChatModel.internalCall() when the ChatCompletion body exists but its choices list is null. Like the null-body case, it returns an empty ChatResponse, so the caller gets a structurally valid response with zero generations instead of an exception.
Source
Thrown at models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java:165
this.observationRegistry)
.observe(() -> {
ResponseEntity<ChatCompletion> completionEntity = RetryUtils.execute(this.retryTemplate,
() -> this.deepSeekApi.chatCompletionEntity(request));
var chatCompletion = completionEntity.getBody();
if (chatCompletion == null) {
if (logger.isWarnEnabled()) {
logger.warn("No chat completion returned for prompt: " + prompt);
}
return new ChatResponse(List.of());
}
List<Choice> choices = chatCompletion.choices();
if (choices == null) {
if (logger.isWarnEnabled()) {
logger.warn("No choices returned for prompt: " + prompt);
}
return new ChatResponse(List.of());
}
List<Generation> generations = choices.stream().map(choice -> {
// @formatter:off
Map<String, Object> metadata = Map.of(
"id", chatCompletion.id() != null ? chatCompletion.id() : "",
"role", choice.message().role() != null ? choice.message().role().name() : "",
"index", choice.index(),
"finishReason", choice.finishReason() != null ? choice.finishReason().name() : "");
// @formatter:on
return buildGeneration(choice, metadata);
}).toList();
// Current usage
ChatCompletion body = completionEntity.getBody();
Assert.state(body != null, "Body must not be null");View on GitHub (pinned to 98a7beda4f)
Solutions
- Log/inspect the full ChatCompletion body (including any error or usage fields) to see why choices are absent.
- Review the prompt for content that DeepSeek may refuse and adjust it.
- Check deepseek API version / spring-ai-deepseek version compatibility after upgrades.
- Handle the empty-generations ChatResponse defensively in application code.
Example fix
// before ChatResponse r = chatModel.call(new Prompt(msg)); return r.getResults().get(0); // IndexOutOfBounds when choices null // after return r.getResults().isEmpty() ? Optional.empty() : Optional.of(r.getResults().get(0));
Defensive patterns
Strategy: type-guard
Type guard
static Optional<Generation> firstGeneration(ChatResponse r) {
return (r == null || r.getResults() == null) ? Optional.empty()
: r.getResults().stream().findFirst();
} Try / catch
Optional<Generation> gen = firstGeneration(chatModel.call(new Prompt(msg)));
Generation g = gen.orElseThrow(() -> new IllegalStateException("DeepSeek returned no choices for prompt")); Prevention
- Never index getResults().get(0) without an emptiness check
- Review prompts for content likely to be filtered
- Pin and test spring-ai-deepseek against your DeepSeek API version after upgrades
When it happens
Trigger: DeepSeek returned a JSON body without a 'choices' field — e.g. an error-shaped payload deserialized into ChatCompletion, a content-filter/empty completion, or an API schema change.
Common situations: Prompts rejected by content filtering; max_tokens or stop conditions producing no choices; DeepSeek API contract changes after model/version upgrades; using an incorrect base-url pointing to a compatible-but-different API.
Related errors
- No chat completion returned for prompt: + prompt
- Chat completion is not supported for this model:
- Unsupported message type:
- Currently only one tool call is supported per message!
- Thinking mode does not support the parameter(s). Please not
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/05a80a44a3501bc4.
Report an issue: GitHub.