alibaba/spring-ai-alibaba · error · RuntimeException
ChatClient Call Return Null...
Error message
ChatClient Call Return Null...
What it means
AgentNode.apply throws this RuntimeException when ChatClient.call().content() returns null after the retry-wrapped invocation, i.e. the model produced no textual content. The node logs a warning then fails fast because downstream nodes expect a non-null string output under outputKey.
Source
Thrown at spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/node/AgentNode.java:134
}
@Override
public Map<String, Object> apply(OverAllState state) throws Exception {
String userPrompt = new PromptTemplate(this.userPrompt).render(state.data());
String systemPrompt = new PromptTemplate(this.systemPrompt).render(state.data());
String output = switch (this.strategy) {
case TOOL_CALLING, REACT -> {
// Retry mechanism
try {
yield this.retryTemplate.execute(retryContext -> {
String content = this.chatClient.prompt(systemPrompt)
.toolCallbacks(this.toolCallbacks)
.user(userPrompt)
.call()
.content();
if (content == null) {
logger.warn("ChatClient Call Return Null...");
throw new RuntimeException("ChatClient Call Return Null...");
}
return content;
});
}
catch (Exception e) {
logger.error("Attempted to the maximum number of times but still failed!");
yield null;
}
}
};
return Map.of(this.outputKey, output == null ? "" : output);
}
public static Builder builder() {
return new Builder();
}
public static class Builder {View on GitHub (pinned to f82da0b50f)
Solutions
- Check the model response in logs to see why content is null (tool calls, filtering, token limit)
- Raise max_tokens or adjust prompts so the model produces final text
- Verify tool execution/conversion so the loop ends with a textual answer
- Wrap apply/call sites in try-catch and provide a fallback output value
Example fix
// before
String content = chatClient.prompt().user(userPrompt).call().content();
// after
String content = chatClient.prompt().user(userPrompt).call().content();
if (content == null || content.isBlank()) { content = "(no content generated)"; } Defensive patterns
Strategy: try-catch
Validate before calling
// verify model reachable and producing content in a preflight call
String probe = chatClient.prompt().user("ping").call().content();
if (probe == null || probe.isBlank()) throw new IllegalStateException("model returns empty content"); Try / catch
try {
output = agentNode.apply(state);
} catch (RuntimeException e) {
if (e.getMessage().contains("Return Null")) {
state.put(outputKey, fallbackAnswer);
} else throw e;
} Prevention
- Set adequate max_tokens and avoid prompts that end in pure tool-call loops
- Inspect raw ChatResponse (not just content()) when debugging empty answers
- Configure the retryTemplate with backoff for transient provider hiccups
When it happens
Trigger: The chat model returns an empty/no-content response (e.g. the response contains only tool calls that were not executed, a stop with no text, or an empty completion) while running the agent's RetryTemplate callback.
Common situations: Model configured with tools but no final text answer generated; max_tokens set so low the response is empty; provider returns empty content on safety-filtered prompts; using a model/adapter whose content mapping yields null.
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
- ChatClient error
- ${response.getResult()}
- Async tool execution failed
- RuntimeException wrapping transaction failure (no literal me
- Failed to delete JAR files from working directory
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/5da7985914fc6b63.
Report an issue: GitHub.