{"record":{"id":"2bda127272af53e1","repo":"alibaba/spring-ai-alibaba","slug":"action-must-be-either-asynccommandaction-or-asyncm","errorCode":null,"errorMessage":"Action must be either AsyncCommandAction or AsyncMultiCommandAction","messagePattern":"Action must be either AsyncCommandAction or AsyncMultiCommandAction","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/internal/edge/EdgeCondition.java","lineNumber":38,"sourceCode":"\nimport java.util.Map;\n\nimport static java.lang.String.format;\n\n/**\n * Represents a condition associated with an edge in a graph.\n * Supports both single-node routing (AsyncCommandAction) and multi-node parallel routing (AsyncMultiCommandAction).\n *\n * @param action The action to be performed asynchronously when the edge condition is met.\n *               Can be either AsyncCommandAction (single node) or AsyncMultiCommandAction (multiple nodes).\n * @param mappings A map of string key-value pairs representing additional mappings for\n * the edge condition.\n */\npublic record EdgeCondition(Object action, Map<String, String> mappings) {\n\n\tpublic EdgeCondition {\n\t\tif (action != null && !(action instanceof AsyncCommandAction) && !(action instanceof AsyncMultiCommandAction)) {\n\t\t\tthrow new IllegalArgumentException(\"Action must be either AsyncCommandAction or AsyncMultiCommandAction\");\n\t\t}\n\t}\n\n\t/**\n\t * Creates an EdgeCondition with AsyncCommandAction (single node routing).\n\t */\n\tpublic static EdgeCondition single(AsyncCommandAction action, Map<String, String> mappings) {\n\t\treturn new EdgeCondition(action, mappings);\n\t}\n\n\t/**\n\t * Creates an EdgeCondition with AsyncMultiCommandAction (multi-node parallel routing).\n\t */\n\tpublic static EdgeCondition multi(AsyncMultiCommandAction action, Map<String, String> mappings) {\n\t\treturn new EdgeCondition(action, mappings);\n\t}\n\n\t/**","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/internal/edge/EdgeCondition.java#L20-L56","documentation":"EdgeCondition is a record whose compact constructor validates that its action is either an AsyncCommandAction or an AsyncMultiCommandAction. Passing any other object (plain action, lambda of the wrong type, null handled separately) throws IllegalArgumentException.","triggerScenarios":"Constructing EdgeCondition directly with a non-async action object — e.g. passing a synchronous NodeAction/CommandAction or an arbitrary lambda where an AsyncCommandAction/AsyncMultiCommandAction is required.","commonSituations":"Custom routing edges built manually instead of via the provided factory methods (AsyncNodeAction.makeAsync etc.); refactors after upgrading from synchronous action APIs; confused generic suppliers typed as Object.","solutions":["Wrap the action with AsyncNodeAction.makeAsync(...) / the appropriate async adapter before building the EdgeCondition.","Use EdgeCondition's provided factory methods (which produce correctly typed async actions) rather than the raw constructor.","For multi-branch routing, implement AsyncMultiCommandAction returning a Command with goto nodes."],"exampleFix":"// before\nnew EdgeCondition(state -> \"nodeA\", mappings);\n// after\nnew EdgeCondition(AsyncNodeAction.makeAsync(state -> \"nodeA\"), mappings);","handlingStrategy":"type-guard","validationCode":"// Verify action type before constructing EdgeCondition\nif (!(action instanceof AsyncCommandAction) && !(action instanceof AsyncMultiCommandAction)) {\n    throw new IllegalArgumentException(\"wrap with makeAsync first\");\n}","typeGuard":"boolean isEdgeConditionAction(Object a) { return a instanceof AsyncCommandAction || a instanceof AsyncMultiCommandAction; }","tryCatchPattern":"try { new EdgeCondition(action, mappings); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"AsyncCommandAction\")) { action = AsyncNodeAction.makeAsync(rawAction); } }","preventionTips":["Always adapt raw actions with AsyncNodeAction.makeAsync","Use EdgeCondition factory methods instead of the raw constructor","After upgrading, recheck actions previously built synchronously","Keep routing lambdas explicitly typed as async action interfaces"],"tags":["routing","type-mismatch","conditional-edge","constructor-validation"],"backgroundTag":"invalid-argument-value","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"}