{"record":{"id":"88c6579e4e9e6acc","repo":"spring-projects/spring-ai","slug":"no-choices-returned-for-prompt-prompt-88c657","errorCode":null,"errorMessage":"No choices returned for prompt: ${prompt}","messagePattern":"No choices returned for prompt: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java","lineNumber":228,"sourceCode":"\t\tChatCompletionCreateParams request = this.createRequest(prompt, false);\n\t\tRequestOptions requestOptions = this.buildRequestOptions(prompt);\n\n\t\tChatModelObservationContext observationContext = ChatModelObservationContext.builder()\n\t\t\t.prompt(prompt)\n\t\t\t.provider(AiProvider.OPENAI.value())\n\t\t\t.build();\n\n\t\tChatResponse response = ChatModelObservationDocumentation.CHAT_MODEL_OPERATION\n\t\t\t.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,\n\t\t\t\t\tthis.observationRegistry)\n\t\t\t.observe(() -> {\n\n\t\t\t\tChatCompletion chatCompletion = this.openAiClient.chat().completions().create(request, requestOptions);\n\n\t\t\t\tList<ChatCompletion.Choice> choices = chatCompletion.choices();\n\t\t\t\tif (choices.isEmpty()) {\n\t\t\t\t\tif (logger.isWarnEnabled()) {\n\t\t\t\t\t\tlogger.warn(\"No choices returned for prompt: \" + prompt);\n\t\t\t\t\t}\n\t\t\t\t\treturn new ChatResponse(List.of());\n\t\t\t\t}\n\n\t\t\t\tList<Generation> generations = choices.stream().map(choice -> {\n\t\t\t\t\tMap<String, Object> metadata = Map.of(\"id\", chatCompletion.id(), \"role\",\n\t\t\t\t\t\t\tchoice.message()._role().asString().isPresent() ? choice.message()._role().asStringOrThrow()\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\"index\", choice.index(), \"finishReason\", choice.finishReason().value().toString(),\n\t\t\t\t\t\t\t\"refusal\", choice.message().refusal().orElse(\"\"), \"annotations\",\n\t\t\t\t\t\t\tchoice.message().annotations().orElse((List) List.of(Map.of())), REASONING_CONTENT,\n\t\t\t\t\t\t\tgetReasoningContent(choice));\n\t\t\t\t\treturn buildGeneration(choice, metadata, request);\n\t\t\t\t}).toList();\n\n\t\t\t\t// Current usage\n\t\t\t\tCompletionUsage usage = chatCompletion.usage().orElse(null);\n\t\t\t\tUsage currentChatResponseUsage = usage != null ? getDefaultUsage(usage) : new EmptyUsage();","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java#L210-L246","documentation":"OpenAiChatModel.internalCall sends a chat completion request to the OpenAI API and checks the returned ChatCompletion. When the API responds successfully but the choices list is empty, Spring AI logs a warning and returns an empty ChatResponse instead of throwing, because there are no generations to build. This usually signals the provider accepted the request but produced no candidate completions.","triggerScenarios":"Calling OpenAiChatModel.call(prompt) where the OpenAI API returns a ChatCompletion whose choices() list is empty — e.g. the request was filtered by content policy, the API returned a degenerate/empty response, or an unexpected response shape from a non-standard endpoint.","commonSituations":"Pointing spring.ai.openai.base-url at a non-OpenAI OpenAI-compatible proxy that omits the choices array; safety filtering of flagged prompts; API version changes that change response shape.","solutions":["Check the response object / enable DEBUG logging to see the raw API response and why choices were empty","If using a proxy or compatible endpoint, verify it returns a standard choices array in the OpenAI chat completion schema","Rephrase the prompt if content filtering may have suppressed the output","Handle the empty ChatResponse in your code: check ChatResponse.getResults() is non-empty before reading generations"],"exampleFix":"// before\nChatResponse response = chatModel.call(new Prompt(\"...\"));\nString text = response.getResult().getOutput().getText(); // NPE if empty\n// after\nChatResponse response = chatModel.call(new Prompt(\"...\"));\nif (response == null || response.getResults().isEmpty()) {\n    throw new IllegalStateException(\"Model returned no completions\");\n}\nString text = response.getResult().getOutput().getText();","handlingStrategy":"validation","validationCode":"// after the call\nChatResponse resp = chatModel.call(prompt);\nif (resp == null || resp.getResults() == null || resp.getResults().isEmpty()) {\n    throw new IllegalStateException(\"OpenAI returned no choices for prompt\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check ChatResponse.getResults() non-empty before reading getResult()","Log raw API responses when using OpenAI-compatible proxies","Rephrase prompts that may be content-filtered"],"tags":["openai","empty-response","chat-completion"],"backgroundTag":"empty-api-response","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}