{"record":{"id":"497b25c167edd51e","repo":"flowable/flowable-engine","slug":"couldn-t-resolve-collection-expression-collection","errorCode":null,"errorMessage":"Couldn't resolve collection expression${collectionExpression details}","messagePattern":"Couldn't resolve collection expression(.+?)","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java","lineNumber":507,"sourceCode":"                return (Collection) obj;\n                \n            } else if (obj instanceof Iterable) {\n                return iterableToCollection((Iterable) obj);\n                \n            } else if (obj instanceof String) {\n                Object collectionVariable = execution.getVariable((String) obj);\n                if (collectionVariable instanceof Collection) {\n                    return (Collection) collectionVariable;\n                } else if (collectionVariable instanceof Iterable) {\n                    return iterableToCollection((Iterable) collectionVariable);\n                } else if (collectionVariable == null) {\n                    throw new FlowableIllegalArgumentException(\"Variable '\" + obj + \"' was not found\");\n                } else {\n                    throw new FlowableIllegalArgumentException(\"Variable '\" + obj + \"':\" + collectionVariable + \" is not a Collection\");\n                }\n                \n            } else {\n                throw new FlowableIllegalArgumentException(buildUnresolvedCollectionExceptionMessage());\n            }\n        }\n    }\n\n    protected String buildUnresolvedCollectionExceptionMessage() {\n        StringBuilder exceptionStringBuilder = new StringBuilder(\"Couldn't resolve collection expression\");\n        if (collectionExpression != null) {\n            exceptionStringBuilder.append(\" (\");\n            exceptionStringBuilder.append(collectionExpression.getExpressionText());\n            exceptionStringBuilder.append(\")\");\n        }\n        exceptionStringBuilder.append(\", variable reference\");\n        if (collectionVariable != null) {\n            exceptionStringBuilder.append(\" (\");\n            exceptionStringBuilder.append(collectionVariable);\n            exceptionStringBuilder.append(\")\");\n        }\n        exceptionStringBuilder.append(\" or string\");","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java#L489-L525","documentation":"Thrown by MultiInstanceActivityBehavior.resolveAndValidateCollection (via buildUnresolvedCollectionExceptionMessage) when the multi-instance activity was configured with a collection expression, but evaluating that expression did not yield a Collection. The appended details identify the expression that failed.","triggerScenarios":"flowable:collection=\"${someExpression}\" where the expression evaluates to null or to a non-Collection value (String, Map, single object) when the multi-instance behavior runs.","commonSituations":"Expression referencing a variable that is null at execution time; expression calling a bean method returning the wrong type; expression typo producing null; elision/property navigation failing silently and returning null; expression returning a Java array which is not a Collection.","solutions":["Fix the expression so it evaluates to a Collection/Iterable, e.g. '${userService.getAssignees(execution)}' returning List.","Null-check/initialize the underlying variables or bean results before the activity executes.","Convert arrays to List at the source (Arrays.asList) since arrays are not Collections.","Verify the bean used in the expression is registered in the process engine configuration beans map.","Test the expression in isolation (e.g. in a small unit test with the expression manager) to see its actual value."],"exampleFix":"// before: bean returns an array\npublic String[] getAssignees() { ... }\n// after: return a Collection\npublic List<String> getAssignees() { return Arrays.asList(\"kermit\", \"gonzo\"); }","handlingStrategy":"validation","validationCode":"Object resolved = expressionManager.createExpression(\"${userService.getAssignees(execution)}\").getValue(execution);\nif (!(resolved instanceof Collection)) {\n    throw new IllegalStateException(\"collection expression must yield a Collection, got: \"\n        + (resolved == null ? \"null\" : resolved.getClass().getName()));\n}","typeGuard":null,"tryCatchPattern":"try {\n    return task.execute(execution);\n} catch (FlowableIllegalArgumentException ex) {\n    if (ex.getMessage().startsWith(\"Couldn't resolve collection expression\")) {\n        logger.error(\"Collection expression returned non-collection: {}\", ex.getMessage());\n    }\n    throw ex;\n}","preventionTips":["Ensure expression-targeted bean methods return Collection/Iterable.","Null-check variables referenced inside collection expressions before the activity.","Convert arrays to List at the source.","Register and test expression beans in the engine configuration before deployment."],"tags":["bpmn","multi-instance","expression","collection"],"backgroundTag":"unexpected-response-shape","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}