{"record":{"id":"0725d830808cd1a3","repo":"alibaba/spring-ai-alibaba","slug":"iteration-start-node-error-wraps-caught-exception","errorCode":null,"errorMessage":"Iteration Start node error (wraps caught exception)","messagePattern":"Iteration Start node error \\(wraps caught exception\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/node/IterationNode.java","lineNumber":139,"sourceCode":"\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Read list and indexes from state\n\t\t\t\t\tlist = (List<ElementInput>) state.value(this.inputArrayKey).orElseThrow();\n\t\t\t\t\tindexes = (List<Integer>) state.value(this.taskIndexListKey).orElseThrow();\n\t\t\t\t}\n\n\t\t\t\tif (indexes.isEmpty()) {\n\t\t\t\t\treturn Map.of(this.outputStartIterationKey, false);\n\t\t\t\t}\n\t\t\t\t// Get the first element to process\n\t\t\t\tint index = indexes.get(0);\n\t\t\t\tindexes.remove(0);\n\t\t\t\treturn Map.of(this.outputItemKey, list.get(index), this.outputStartIterationKey, true,\n\t\t\t\t\t\tthis.taskIndexListKey, indexes, this.inputArrayKey, list);\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.error(\"Iteration Start node error: {}\", e.getMessage(), e);\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t}\n\n\t\tpublic static class Builder<ElementInput> {\n\n\t\t\tprivate String inputArrayJsonKey;\n\n\t\t\tprivate String inputArrayKey;\n\n\t\t\tprivate String outputItemKey;\n\n\t\t\tprivate String outputStartIterationKey;\n\n\t\t\tprivate String taskIndexListKey;\n\n\t\t\tpublic Start<ElementInput> build() {\n\t\t\t\treturn new Start<>(inputArrayJsonKey, inputArrayKey, taskIndexListKey, outputItemKey,\n\t\t\t\t\t\toutputStartIterationKey);","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/node/IterationNode.java#L121-L157","documentation":"IterationNode's start node (apply) extracts the element at the current index from the input array state. Any exception during that work (missing input array key, non-list input, JSON issues, index problems) is logged and rethrown wrapped in a RuntimeException. The message 'Iteration Start node error' is the log line; the thrown exception wraps the real cause, so the root cause is in getCause().","triggerScenarios":"Running a state graph containing an IterationNode start node when the input array key is absent from state, the value is not a list/array, the input array is empty at index access, or the sub-state keys were configured incorrectly.","commonSituations":"Upstream node didn't produce the expected array before iteration began; key name mismatch between builder config (inputArrayJsonKey) and actual state keys; JSON input string malformed.","solutions":["Read the wrapped cause: e.getCause().getMessage() holds the real failure.","Verify the input array key exists in OverAllState before the iteration graph runs and holds a non-empty List.","Confirm the Builder's inputArrayJsonKey/output keys match the state keys used by upstream nodes.","Add a validation/checkpoint node ahead of the loop to guarantee array presence."],"exampleFix":"// before\ncatch (Exception e) {\n    log.error(\"Iteration Start node error: {}\", e.getMessage(), e);\n    throw new RuntimeException(e);\n}\n// after\ncatch (Exception e) {\n    log.error(\"Iteration Start node error\", e);\n    throw new RuntimeException(\"Iteration Start node failed\", e); // preserve cause chain\n}","handlingStrategy":"validation","validationCode":"Object arr = state.value(inputArrayJsonKey).orElse(null);\nif (!(arr instanceof List<?> list) || list.isEmpty()) {\n    throw new IllegalStateException(\"Iteration input '\" + inputArrayJsonKey + \"' must be a non-empty List\");\n}","typeGuard":"boolean isValidIterationInput(OverAllState state, String key) {\n    return state.value(key).map(v -> v instanceof List<?> l && !l.isEmpty()).orElse(false);\n}","tryCatchPattern":"try {\n    result = iterationStartNode.apply(state);\n} catch (RuntimeException e) {\n    Throwable cause = e.getCause();\n    log.error(\"Iteration start failed: {}\", cause == null ? e : cause);\n    throw cause instanceof RuntimeException re ? re : e;\n}","preventionTips":["Always populate the input array key before the iteration subgraph runs.","Keep builder key names in constants shared with upstream nodes.","Test iteration graphs with empty and single-element arrays.","Never swallow the cause chain when rethrowing."],"tags":["iteration-node","wrapped-exception","state-graph"],"backgroundTag":"internal-invariant-violation","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}