alibaba/spring-ai-alibaba · error · RuntimeException
input is not String
Error message
input is not String
What it means
ListOperatorNode.apply reads the value at inputKey from OverAllState. In JSON_STR mode it requires that value to be a Java String containing JSON; if it is any other type (List, Map, number, null) this RuntimeException is thrown. The node deliberately refuses to coerce so malformed workflow state fails fast at the boundary.
Solutions
- Switch the Builder mode to Mode.LIST (or ARRAY) if the upstream value is already a List/array.
- Ensure the upstream node serializes its output to a JSON string before this node.
- Verify inputKey matches the key the upstream node actually writes.
- Wrap apply in error handling that reports the actual type of state.value(inputKey).
Example fix
// before
ListOperatorNode.<Item>start().mode(Mode.JSON_STR).inputKey("items")... // upstream emits List<Item>
// 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 instanceof String s)) throw new IllegalStateException("'items' must be a JSON string, got " + (v == null ? "null" : v.getClass())); Type guard
boolean isJsonStringInput(OverAllState state, String key) {
return state.value(key).map(v -> v instanceof String).orElse(false);
} Try / catch
try {
out = listOperator.apply(state);
} catch (RuntimeException e) {
if ("input is not String".equals(e.getMessage())) {
throw new IllegalStateException("Configure Mode.LIST or serialize upstream output", e);
}
throw e;
} Prevention
- Match the Builder mode to the upstream node's output type.
- Keep upstream serialization contracts documented per state key.
- Validate state types in a pre-check node in dev/test runs.
- Use constants for state keys to avoid silent nulls.
When it happens
Trigger: Mode is set to Builder Mode.JSON_STR but the state value under inputKey is not a String — e.g. an upstream node already produced a parsed List, or the key is missing (value null).
Common situations: Upstream node outputs a real List while ListOperatorNode was configured for JSON string mode; config copied from a JSON-mode example; missing upstream output leaves null in state.
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 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/deb8f358dad88cba.
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:90
private ListOperatorNode(Mode mode, String inputKey, String outputKey, Predicate<T> filterChain,
Comparator<T> comparatorChain, Long limitNumber, Class<T> type) {
this.mode = mode;
this.inputKey = inputKey;
this.outputKey = outputKey;
this.filterChain = filterChain;
this.comparatorChain = comparatorChain;
this.limitNumber = limitNumber;
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);
}
};View on GitHub (pinned to f82da0b50f)