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

  1. Switch the Builder mode to Mode.LIST (or ARRAY) if the upstream value is already a List/array.
  2. Ensure the upstream node serializes its output to a JSON string before this node.
  3. Verify inputKey matches the key the upstream node actually writes.
  4. 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

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


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)