spring-projects/spring-ai · error · IllegalArgumentException
List items must be of type String
Error message
List items must be of type String
What it means
SyncMcpCompleteMethodCallback.convertToCompleteResult throws this IllegalArgumentException when a @McpComplete method returns a List whose elements are not all String instances. The completion protocol only supports string suggestions, so any non-String element (Integer, POJO, null) makes the result unconvertible.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/SyncMcpCompleteMethodCallback.java:112
if (result instanceof CompleteResult) {
return (CompleteResult) result;
}
if (result instanceof CompleteCompletion) {
return new CompleteResult((CompleteCompletion) result);
}
if (result instanceof List) {
List<?> list = (List<?>) result;
List<String> values = new ArrayList<>();
for (Object item : list) {
if (item instanceof String) {
values.add((String) item);
}
else {
throw new IllegalArgumentException("List items must be of type String");
}
}
return new CompleteResult(new CompleteCompletion(values, values.size(), false));
}
if (result instanceof String) {
return new CompleteResult(new CompleteCompletion(List.of((String) result), 1, false));
}
throw new IllegalArgumentException("Unsupported return type: " + result.getClass().getName());
}
/**
* Validates that the method return type is compatible with the complete callback.
* @param method The method to validate
* @throws IllegalArgumentException if the return type is not compatible
*/View on GitHub (pinned to 98a7beda4f)
Solutions
- Ensure the returned List contains only String elements
- Convert non-String values to strings explicitly with String.valueOf(item) or item.toString() before returning
- Filter out null or non-String entries before returning the list
- Change the method signature to List<String> so the compiler enforces element type
Example fix
// before
return Arrays.asList("a.txt", 42);
// after
return Arrays.asList("a.txt", "42"); Defensive patterns
Strategy: validation
Validate before calling
List<?> values = myCompleteMethodResult();
if (values.stream().anyMatch(v -> !(v instanceof String)))
throw new IllegalStateException("completion list must contain only Strings"); Type guard
static boolean isStringList(Object o) {
return o instanceof List<?> l && l.stream().allMatch(String.class::isInstance);
} Try / catch
try { CompleteResult r = callback.apply(ctx, req); }
catch (IllegalArgumentException e) { log.error("bad completion payload: {}", e.getMessage()); return new CompleteResult(new CompleteCompletion(List.of(), 0, false)); } Prevention
- Declare handler return types as List<String> so generics enforce element type
- Never return raw (unparameterized) List from a completion handler
- Unit-test handlers by calling convertToCompleteResult directly
When it happens
Trigger: A @McpComplete handler method returns List<Integer>, List<Object>, a List mixing strings and non-strings, or a List containing null entries; convertToCompleteResult is invoked from apply() while handling a completion request from the MCP client.
Common situations: Developers return domain objects or enums as completion values, or collect heterogeneous values from a database into one list, forgetting that MCP completions must be plain strings.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- List items must be of type String
- List items must be of type String
- Parameter must be of type List<McpSchema.Resource>:
- Either prompt or uri must be provided!
- Unsupported return type: {resultType}
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/99b754120c76e9b1.
Report an issue: GitHub.