spring-projects/spring-ai · warning

No chat completion returned for prompt: + prompt

Error message

No chat completion returned for prompt: + prompt

What it means

Warning logged by DeepSeekChatModel.internalCall() when the HTTP response body from deepSeekApi.chatCompletionEntity() is null — i.e. DeepSeek returned no ChatCompletion object at all. The method returns an empty ChatResponse (empty generations list) instead of throwing, so callers see a response with no content rather than an error.

Source

Thrown at models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java:157

		ChatModelObservationContext observationContext = ChatModelObservationContext.builder()
			.prompt(prompt)
			.provider(DeepSeekConstants.PROVIDER_NAME)
			.build();

		ChatResponse response = ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
			.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
					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(),

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Check the DeepSeek API status and your API key validity; an auth or server problem often surfaces as a null body.
  2. Enable wire-level logging (e.g. RestClient/RestTemplate interceptor) to inspect the raw HTTP response.
  3. Guard the caller against ChatResponse with empty generations before using getResult().
  4. Configure the RetryTemplate with a backoff for transient empty responses.

Example fix

// before
ChatResponse response = chatModel.call(new Prompt(prompt));
String text = response.getResult().getOutput().getText(); // NPE if empty
// after
String text = (response.getResults() == null || response.getResults().isEmpty())
        ? "" : response.getResult().getOutput().getText();
Defensive patterns

Strategy: try-catch

Validate before calling

Assert.hasText(apiKey, "DeepSeek API key must be set"); // and verify endpoint reachability before batch jobs

Type guard

static boolean isEmpty(ChatResponse r) { return r == null || r.getResults() == null || r.getResults().isEmpty(); }

Try / catch

ChatResponse r = chatModel.call(new Prompt(prompt));
if (isEmpty(r)) { metrics.increment("deepseek.empty.response"); return fallbackAnswer; }

Prevention

When it happens

Trigger: deepseekApi.chatCompletionEntity(request) executes successfully via RetryUtils but ResponseEntity.getBody() is null — server returned an empty body, or a non-deserializable/empty payload after retries.

Common situations: DeepSeek API outages or partial incidents returning 200 with empty body; proxy/gateway stripping the body; invalid DeepSeek API key hitting an endpoint that returns an unexpected empty response; transient network issues that exhausted retries with empty results.

Related errors


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