alibaba/spring-ai-alibaba · error · RuntimeException
input is not Array
Error message
input is not Array
What it means
In ARRAY mode, ListOperatorNode.apply requires the state value at inputKey to be a non-null Java array (inputObject.getClass().isArray()). If the value is null or not an array (List, String, etc.) this RuntimeException is thrown before the Arrays.asList cast.
Solutions
- Use Mode.LIST instead — Jackson and most nodes produce Lists, not arrays.
- Ensure the upstream node genuinely writes a primitive/object array under inputKey.
- Add a null/type check on t.value(inputKey) in an upstream validation step.
- Wrap in try-catch mapping this error to a workflow-level failure message.
Example fix
// before
ListOperatorNode.<Item>start().mode(Mode.ARRAY).inputKey("items")... // items is a List
// after
ListOperatorNode.<Item>start().mode(Mode.LIST).inputKey("items")... Defensive patterns
Strategy: type-guard
Validate before calling
Object v = state.value("items").orElse(null);
if (v == null || !v.getClass().isArray()) throw new IllegalStateException("'items' must be an array, got " + (v == null ? "null" : v.getClass())); Type guard
boolean isArrayInput(OverAllState state, String key) {
return state.value(key).map(v -> v != null && v.getClass().isArray()).orElse(false);
} Try / catch
try {
out = listOperator.apply(state);
} catch (RuntimeException e) {
if ("input is not Array".equals(e.getMessage())) {
throw new IllegalStateException("State holds no array; prefer Mode.LIST for JSON-sourced data", e);
}
throw e;
} Prevention
- Avoid Mode.ARRAY unless a node explicitly emits Java arrays.
- JSON arrays deserialize to Lists, not arrays — use LIST.
- Check for null state values before graph execution.
- Prefer LIST mode as the default and document exceptions.
When it happens
Trigger: Mode ARRAY configured while the state value under inputKey is null, a List, or a String; upstream node never ran or wrote a different structure.
Common situations: Assuming JSON arrays in state become Java arrays (they become Lists via Jackson); passing optional state values that may be absent.
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 List
- input is not String
- 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/42cd7af5e7e95456.
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:104
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);
case LIST -> listElements;
case ARRAY -> listElements.toArray();
};
return Map.of(outputKey, output);
}View on GitHub (pinned to f82da0b50f)