alibaba/spring-ai-alibaba · error · RuntimeException
input is not List
Error message
input is not List
What it means
In LIST mode, ListOperatorNode.apply requires the state value at inputKey to be an instance of java.util.List. If it is anything else (a JSON string, array, null) this RuntimeException is thrown. It's a runtime type guard so the subsequent (List<T>) cast is safe.
Solutions
- Set mode to JSON_STR if the upstream value is a JSON string.
- Ensure the upstream node writes an actual List under inputKey.
- Check for state-key collisions where another node overwrites the value.
- Add a pre-check node validating the state value type before ListOperatorNode runs.
Example fix
// before
ListOperatorNode.<Item>start().mode(Mode.LIST).inputKey("items")... // items is a JSON string
// after
ListOperatorNode.<Item>start().mode(Mode.JSON_STR).inputKey("items")... Defensive patterns
Strategy: type-guard
Validate before calling
Object v = state.value("items").orElse(null);
if (!(v instanceof List)) throw new IllegalStateException("'items' must be a List for Mode.LIST, got " + (v == null ? "null" : v.getClass())); Type guard
boolean isListInput(OverAllState state, String key) {
return state.value(key).map(v -> v instanceof List<?>).orElse(false);
} Try / catch
try {
out = listOperator.apply(state);
} catch (RuntimeException e) {
if ("input is not List".equals(e.getMessage())) {
throw new IllegalStateException("Upstream emitted non-List for key; switch mode or fix upstream", e);
}
throw e;
} Prevention
- Only use Mode.LIST when the producer writes a real java.util.List.
- Remember Jackson JSON parsing yields Lists, not Strings — prefer LIST mode after parsing.
- Guard against state-key overwrites between nodes.
- Add integration tests across node boundaries.
When it happens
Trigger: Mode LIST configured while upstream node wrote a JSON string, a primitive array, a Map, or nothing (null) under inputKey.
Common situations: Mixing nodes that emit JSON strings with nodes expecting structured lists; refactoring upstream output from List to serialized JSON; key collisions in OverAllState overwriting the list.
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
- input is not String
- input is not Array
- Action must be either AsyncCommandAction or…
- App spec is not Agent
- Cannot append to non-list value for key
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/fed2c88b8cb99854.
Report an issue: GitHub.
Appendix: source
Thrown at spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/node/ListOperatorNode.java:98
this.type = type;
}
@Override
public Map<String, Object> apply(OverAllState t) throws Exception {
try {
Object inputObject = t.value(inputKey).orElse(null);
List<T> inputList = switch (mode) {
case JSON_STR -> {
if (!(inputObject instanceof String)) {
throw new RuntimeException("input is not String");
}
String inputJsonString = inputObject.toString();
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, type);
yield objectMapper.readValue(inputJsonString, javaType);
}
case LIST -> {
if (!(inputObject instanceof List)) {
throw new RuntimeException("input is not List");
}
yield (List<T>) inputObject;
}
case ARRAY -> {
if (inputObject == null || !inputObject.getClass().isArray()) {
throw new RuntimeException("input is not Array");
}
yield Arrays.asList((T[]) inputObject);
}
};
List<T> listElements = inputList.stream()
.filter(filterChain)
.sorted(comparatorChain)
.limit(limitNumber != null && limitNumber > 0 ? limitNumber : Long.MAX_VALUE)
.toList();
Object output = switch (mode) {
case JSON_STR -> objectMapper.writeValueAsString(listElements);View on GitHub (pinned to f82da0b50f)