spring-projects/spring-ai · error · IllegalArgumentException
clients must not be empty
Error message
clients must not be empty
What it means
The compact constructor of AsyncToolListChangedSpecification validates the `clients` array: it must be non-null, non-empty, and contain no blank entries. This mirrors the sync variant; without at least one client name the async tool-list-changed specification would register against nothing and silently do nothing.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/tool/AsyncToolListChangedSpecification.java:33
*/
package org.springframework.ai.mcp.annotation.method.changed.tool;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import io.modelcontextprotocol.spec.McpSchema;
import reactor.core.publisher.Mono;
public record AsyncToolListChangedSpecification(String[] clients,
Function<List<McpSchema.Tool>, Mono<Void>> toolListChangeHandler) {
public AsyncToolListChangedSpecification {
Objects.requireNonNull(clients, "clients must not be null");
if (clients.length == 0 || Arrays.stream(clients).map(String::trim).anyMatch(String::isEmpty)) {
throw new IllegalArgumentException("clients must not be empty");
}
Objects.requireNonNull(toolListChangeHandler, "toolListChangeHandler must not be null");
}
}
View on GitHub (pinned to 98a7beda4f)
Solutions
- Pass at least one real MCP client name: new AsyncToolListChangedSpecification(new String[]{"myClient"}, handler)
- Validate/sanitize the client-name source before constructing; filter blanks and fail early if the result is empty
- Check configuration/property binding so the clients list is actually populated at startup
Example fix
// before
AsyncToolListChangedSpecification spec =
new AsyncToolListChangedSpecification(props.getClients().split(","), handler); // [""] when unset
// after
if (props.getClients() == null || props.getClients().isBlank())
throw new IllegalStateException("At least one MCP client must be configured");
String[] clients = java.util.Arrays.stream(props.getClients().split(","))
.map(String::trim).filter(s -> !s.isEmpty()).toArray(String[]::new);
AsyncToolListChangedSpecification spec = new AsyncToolListChangedSpecification(clients, handler); Defensive patterns
Strategy: validation
Validate before calling
if (clients == null || clients.length == 0 || java.util.Arrays.stream(clients).map(String::trim).anyMatch(String::isEmpty)) { throw new IllegalArgumentException("clients must contain at least one non-blank name"); } Type guard
static boolean validClients(String[] clients) { return clients != null && clients.length > 0 && java.util.Arrays.stream(clients).noneMatch(c -> c == null || c.trim().isEmpty()); } Try / catch
try { new AsyncToolListChangedSpecification(clients, handler); } catch (IllegalArgumentException e) { log.error("Bad clients argument: {}", e.getMessage()); } Prevention
- Sanitize the client-name source (trim/filter) before constructing the specification
- Verify the clients property is bound and non-empty at startup
- Cover the registration path with a test for the empty-clients case
When it happens
Trigger: Constructing new AsyncToolListChangedSpecification(new String[0], handler) or with only blank entries like new String[]{" ", ""} — either clients.length == 0 or the anyMatch(String::isEmpty) predicate throws IllegalArgumentException.
Common situations: Client names sourced from empty configuration properties, splitting an empty/unset comma-separated string into [""], or a wiring error where the array is built after an async lookup that returned no clients.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- clients must not be empty
- Method must have exactly 1 parameter (List<McpSchema.Resourc
- Method must have void or Mono<Void> return type:
- Method must have void return type: " + method.getName() + "
- Method must have void return type:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/f71e01534ea740d7.
Report an issue: GitHub.