alibaba/spring-ai-alibaba · error · RuntimeException
Variable fileList is not an ArrayFileSegment
Error message
Variable fileList is not an ArrayFileSegment
What it means
DocumentExtractorNode.apply throws this RuntimeException in the inputIsArray branch when, after attempting to coerce the state value, fileList is null or empty — i.e. the value at paramsKey was not a usable ArrayFileSegment (list of file segments).
Solutions
- Make the upstream node emit an ArrayFileSegment (list of file segments) under paramsKey
- Set inputIsArray=false if the input is actually a single file
- Log/inspect the actual type of state.value(paramsKey) and align it with the extractor's expectation
Example fix
// before
state.put("files", singleFileString); // node has inputIsArray=true
// after
state.put("files", List.of(fileSegment1, fileSegment2)); Defensive patterns
Strategy: type-guard
Validate before calling
Object v = state.value(paramsKey).orElse(null);
if (inputIsArray && !(v instanceof List<?> list && !list.isEmpty())) {
throw new IllegalStateException("paramsKey must hold a non-empty ArrayFileSegment list");
} Type guard
static boolean isArrayFileSegment(Object v) {
return v instanceof List<?> l && !l.isEmpty() && l.get(0) instanceof FileSegment;
} Try / catch
try {
out = extractorNode.apply(state);
} catch (RuntimeException e) {
logger.error("fileList shape wrong: {}", e.getMessage());
out = Map.of(outputKey, List.of());
} Prevention
- Match inputIsArray to the actual shape of the state value (array vs single file)
- Have the upstream node emit ArrayFileSegment explicitly when inputIsArray=true
- Add a state-shape assertion between producer and consumer nodes
When it happens
Trigger: inputIsArray=true but the state value under paramsKey is a single string, a Map, or an object that fails conversion to a list of files, leaving fileList null after the catch block sets it to null.
Common situations: Upstream node writes a single file string while the extractor expects an array of ArrayFileSegment; state key never populated; shape change after upgrading the file-segment representation; JSON-deserialized state loses the segment type.
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
- Action must be either AsyncCommandAction or…
- App spec is not Agent
- Cannot append to non-list value for key
- Cannot merge incompatible types
- chatOptions type ( ) should be consistent with the default…
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/a1f7734b1533c507.
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/DocumentExtractorNode.java:140
if (this.inputIsArray) {
if (fileObj instanceof List<?>) {
fileList = (List<String>) fileObj;
}
else if (fileObj instanceof String[]) {
fileList = Arrays.asList((String[]) fileObj);
}
else {
// Try to parse as Json string, if failed the input is invalid
try {
fileList = JsonParser.fromJson(fileObj.toString(), new TypeReference<List<String>>() {
});
}
catch (Exception ignore) {
fileList = null;
}
}
if (fileList == null || fileList.isEmpty()) {
throw new RuntimeException("Variable fileList is not an ArrayFileSegment");
}
}
else {
// Single file, add directly to the list
fileList = List.of(fileObj.toString());
}
List<String> documentContents = this.getDocument(fileList);
String key = Optional.ofNullable(this.outputKey).orElse("text");
if (!this.inputIsArray) {
return Map.of(key, documentContents.get(0));
}
else {
return Map.of(key, documentContents);
}
}
private String extractTextByFileExtension(InputStream fileContent, String fileExtension) {View on GitHub (pinned to f82da0b50f)