{"record":{"id":"b3478e9ad8ce7f2a","repo":"spring-projects/spring-ai","slug":"no-content-blocks-returned-for-prompt-prompt","errorCode":null,"errorMessage":"No content blocks returned for prompt: + prompt","messagePattern":"No content blocks returned for prompt: \\+ prompt","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java","lineNumber":568,"sourceCode":"\t\t\t.prompt(prompt)\n\t\t\t.provider(AiProvider.ANTHROPIC.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\tHttpResponseFor<Message> rawResponse = this.anthropicClient.messages()\n\t\t\t\t\t.withRawResponse()\n\t\t\t\t\t.create(request, requestOptionsFor(prompt));\n\t\t\t\tMessage message = rawResponse.parse();\n\t\t\t\tRateLimit rateLimit = AnthropicRateLimit.from(rawResponse.headers());\n\n\t\t\t\tList<ContentBlock> contentBlocks = message.content();\n\t\t\t\tif (contentBlocks.isEmpty()) {\n\t\t\t\t\tif (logger.isWarnEnabled()) {\n\t\t\t\t\t\tlogger.warn(\"No content blocks 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<Citation> citations = new ArrayList<>();\n\t\t\t\tList<AnthropicWebSearchResult> webSearchResults = new ArrayList<>();\n\t\t\t\tList<Generation> generations = buildGenerations(message, citations, webSearchResults);\n\n\t\t\t\t// Current usage\n\t\t\t\tcom.anthropic.models.messages.Usage sdkUsage = message.usage();\n\t\t\t\tUsage currentChatResponseUsage = getDefaultUsage(sdkUsage);\n\t\t\t\tUsage accumulatedUsage = previousChatResponse != null\n\t\t\t\t\t\t? UsageCalculator.getCumulativeUsage(currentChatResponseUsage, previousChatResponse)\n\t\t\t\t\t\t: currentChatResponseUsage;\n\n\t\t\t\tChatResponse chatResponse = new ChatResponse(generations,\n\t\t\t\t\t\tfrom(message, accumulatedUsage, citations, webSearchResults, rateLimit));\n","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java#L550-L586","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nChatResponse response = chatModel.call(new Prompt(\"hi\"));\nString text = response.getResult().getOutput().getText(); // NPE/ISE on empty\n// after\nChatResponse response = chatModel.call(new Prompt(\"hi\"));\nif (response == null || response.getResults().isEmpty()) {\n    logger.warn(\"Anthropic returned no content\");\n    return fallbackAnswer;\n}\nString text = response.getResult().getOutput().getText();","handlingStrategy":"fallback","validationCode":"// before calling, sanity-check options\nif (options.getMaxTokens() == null || options.getMaxTokens() <= 0) {\n    throw new IllegalArgumentException(\"max_tokens must be positive\");\n}","typeGuard":"boolean hasContent(ChatResponse r) {\n    return r != null && r.getResults() != null && !r.getResults().isEmpty()\n        && r.getResult().getOutput() != null;\n}","tryCatchPattern":"ChatResponse resp = chatModel.call(new Prompt(prompt, options));\nif (resp == null || CollectionUtils.isEmpty(resp.getResults())) {\n    logger.warn(\"Empty Anthropic response; using fallback\");\n    return fallbackResponse;\n}","preventionTips":["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"],"tags":["anthropic","empty-response","spring-ai","llm"],"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"}