{"record":{"id":"50497d2c09db3e84","repo":"alibaba/spring-ai-alibaba","slug":"parallelagent-validation-failed-duplicate-output","errorCode":null,"errorMessage":"ParallelAgent validation failed: Duplicate output keys found among sub-agents: []. Each sub-agent must have a unique output key to avoid conflicts during result merging.","messagePattern":"ParallelAgent validation failed: Duplicate output keys found among sub-agents: \\[\\]\\. Each sub-agent must have a unique output key to avoid conflicts during result merging\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/agent/ParallelAgent.java","lineNumber":292,"sourceCode":"\t\t */\n\t\tprivate void validateUniqueOutputKeys() {\n\t\t\tSet<String> outputKeys = new HashSet<>();\n\t\t\tSet<String> duplicateKeys = new HashSet<>();\n\n\t\t\tfor (Agent subAgent : subAgents) {\n\t\t\t\tif (subAgent instanceof ReactAgent subReactAgent) {\n\t\t\t\t\tString outputKey = subReactAgent.getOutputKey();\n\t\t\t\t\tif (outputKey != null) {\n\t\t\t\t\t\tif (!outputKeys.add(outputKey)) {\n\t\t\t\t\t\t\t// This key was already seen, it's a duplicate\n\t\t\t\t\t\t\tduplicateKeys.add(outputKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!duplicateKeys.isEmpty()) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"ParallelAgent validation failed: Duplicate output keys found among sub-agents: \"\n\t\t\t\t\t\t\t\t+ duplicateKeys\n\t\t\t\t\t\t\t\t+ \". Each sub-agent must have a unique output key to avoid conflicts during result merging.\");\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Validates that sub-agents can properly receive data from the parent agent.\n\t\t *\n\t\t * <p>\n\t\t * This validation checks the data flow compatibility by ensuring that:\n\t\t * </p>\n\t\t * <ul>\n\t\t * <li>The parent agent has an outputKey defined</li>\n\t\t * <li>Sub-agents can properly handle the data flow through asAsyncNodeAction</li>\n\t\t * </ul>\n\t\t *\n\t\t * <p>","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/agent/ParallelAgent.java#L274-L310","documentation":"validateUniqueOutputKeys() throws when two or more sub-agents of a ParallelAgent produce results under the same output key. Duplicate keys make the merged result state ambiguous (one agent's output would overwrite another's), so building is aborted and the duplicate key list is reported.","triggerScenarios":"Two sub-agents configured with the same .outputKey(\"result\") (or default key) and passed to one ParallelAgent, then .build() is called.","commonSituations":"Cloning an agent for scale-out without changing its output key; both sub-agents wrapping the same tool; copying a builder block and leaving outputKey unchanged.","solutions":["Give each sub-agent a distinct outputKey in its own configuration","Inspect the reported duplicateKeys list and rename the conflicting keys","Ensure cloned/duplicated agents parameterize their output key"],"exampleFix":"// before\nagentA.builder().outputKey(\"result\"); agentB.builder().outputKey(\"result\");\n// after\nagentA.builder().outputKey(\"resultA\"); agentB.builder().outputKey(\"resultB\");","handlingStrategy":"validation","validationCode":"Set<String> keys = subAgents.stream().map(a -> a.outputKey()).collect(java.util.stream.Collectors.toSet()); if (keys.size() != subAgents.size()) throw new IllegalStateException(\"Duplicate output keys\");","typeGuard":null,"tryCatchPattern":"try { agent = builder.build(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Duplicate output keys\")) { /* reassign keys and rebuild */ } else throw e; }","preventionTips":["Parameterize outputKey when cloning agents","Derive output keys from agent names to keep them unique","Add a startup check that all parallel output keys are distinct"],"tags":["validation","state-merge","output-key"],"backgroundTag":"conflicting-config-options","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}