alibaba/spring-ai-alibaba · error · IllegalArgumentException

Either chatClient or model must be provided

Error message

Either chatClient or model must be provided

What it means

DefaultBuilder.build() requires that at least one of chatClient or model is set; if both are null it throws IllegalArgumentException. A ReactAgent needs an underlying model (directly or through a ChatClient) to run the ReAct loop.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/DefaultBuilder.java:64

public class DefaultBuilder extends Builder {

	private static final Logger logger = LoggerFactory.getLogger(DefaultBuilder.class);

	public static final String POSSIBLE_LLM_TOOL_NAME_CHANGE_WARNING
				= "LLM may have adapted the tool name '{}', especially if the name was truncated due to length limits. If this is the case, you can customize the prefixing and processing logic using McpToolNamePrefixGenerator";

	@Override
	public ReactAgent build() {

		// Validate name is not empty
		if (!StringUtils.hasText(this.name)) {
			throw new IllegalArgumentException("Agent name must not be empty");
		}

		// Validate either chatClient or model is provided
		if (chatClient == null && model == null) {
			throw new IllegalArgumentException("Either chatClient or model must be provided");
		}

		// Get source options from ChatClient (when provided) or from ChatModel (when building from model).
		ChatOptions sourceOptions = (chatClient != null)
				? getChatClientDefaultOptions(chatClient)
				: getChatModelDefaultOptions(model);
		ChatOptions effectiveOptions = mergeSourceOptionsWithAgentOptions(sourceOptions, this.chatOptions);

		if (chatClient == null) {
			ChatClient.Builder clientBuilder = ChatClient.builder(model,
					this.observationRegistry == null ? ObservationRegistry.NOOP : this.observationRegistry,
					this.customObservationConvention, this.advisorObservationConvention);
			if (effectiveOptions != null) {
				clientBuilder.defaultOptions(effectiveOptions);
			}
			chatClient = clientBuilder.build();
		} else {
			chatClient = chatClient.mutate().defaultOptions(effectiveOptions).build();

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Add .model(chatModel) (e.g. DashScopeChatModel) to the builder.
  2. Or add .chatClient(chatClient) built with ChatClient.builder(chatModel).build().
  3. Ensure the model bean exists: configure the DashScope/OpenAI starter and API key so the ChatModel bean is injected.
  4. In tests, pass a stub ChatModel implementation.

Example fix

// before
ReactAgent.builder().name("bot").build();
// after
ReactAgent.builder().name("bot").model(chatModel).build();
Defensive patterns

Strategy: validation

Validate before calling

if (chatClient == null && chatModel == null) throw new IllegalArgumentException("Provide either a ChatClient or a ChatModel to the ReactAgent builder");

Try / catch

try { agent = builder.build(); } catch (IllegalArgumentException e) { log.error("Agent '{}': {}", builderName, e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Calling ReactAgent.builder().name("x").build() without .model(ChatModel) or .chatClient(ChatClient).

Common situations: Forgetting to wire the ChatModel bean (missing DashScope/OpenAI starter config or API key so the bean is absent), or building agents programmatically in tests without stubbing a model.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/477f55a5ecf23986. Report an issue: GitHub.