{"record":{"id":"d408306df50d67dd","repo":"flowable/flowable-engine","slug":"variable-collectionvariable-was-not-found","errorCode":null,"errorMessage":"Variable ${collectionVariable} was not found","messagePattern":"Variable (.+?) was not found","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java","lineNumber":149,"sourceCode":"    }\n\n    // Helpers //////////////////////////////////////////////////////////////////////\n\n    @SuppressWarnings(\"rawtypes\")\n    protected int resolveNrOfInstances(ActivityExecution execution) {\n        int nrOfInstances = -1;\n        if (loopCardinalityExpression != null) {\n            nrOfInstances = resolveLoopCardinality(execution);\n        } else if (collectionExpression != null) {\n            Object obj = collectionExpression.getValue(execution);\n            if (!(obj instanceof Collection)) {\n                throw new ActivitiIllegalArgumentException(collectionExpression.getExpressionText() + \"' didn't resolve to a Collection\");\n            }\n            nrOfInstances = ((Collection) obj).size();\n        } else if (collectionVariable != null) {\n            Object obj = execution.getVariable(collectionVariable);\n            if (obj == null) {\n                throw new ActivitiIllegalArgumentException(\"Variable \" + collectionVariable + \" was not found\");\n            }\n            if (!(obj instanceof Collection)) {\n                throw new ActivitiIllegalArgumentException(\"Variable \" + collectionVariable + \"' is not a Collection\");\n            }\n            nrOfInstances = ((Collection) obj).size();\n        } else {\n            throw new ActivitiIllegalArgumentException(\"Couldn't resolve collection expression nor variable reference\");\n        }\n        return nrOfInstances;\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    protected void executeOriginalBehavior(ActivityExecution execution, int loopCounter) {\n        if (usesCollection() && collectionElementVariable != null) {\n            Collection collection = null;\n            if (collectionExpression != null) {\n                collection = (Collection) collectionExpression.getValue(execution);\n            } else if (collectionVariable != null) {","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java#L131-L167","documentation":"When a multi-instance activity uses flowable:collection pointing at a variable name (collectionVariable) rather than an expression, resolveNrOfInstances fetches that variable from the execution. If the variable does not exist (getVariable returns null), this ActivitiIllegalArgumentException is thrown because the number of instances cannot be determined.","triggerScenarios":"flowable:collection=\"assignees\" on a multi-instance task where variable 'assignees' was never set (or was removed) before the multi-instance activity starts.","commonSituations":"Upstream service task or call-activity output mapping failing silently so the collection variable is never populated; typo in the variable name in flowable:collection; variable set under a different scope (e.g. only in a subprocess) than expected; variable cleared by an earlier listener.","solutions":["Set the collection variable before the multi-instance activity executes (delegate, listener, or input mapping).","Verify the variable name in flowable:collection matches exactly the set variable (case-sensitive).","Check call-activity in/out mappings and service-task output mappings that should produce the variable.","Initialize a default empty List for the variable early in the process instance."],"exampleFix":"<!-- before: variable 'assignees' is never created -->\n<serviceTask id=\"fetch\" flowable:delegateExpression=\"${fetcher}\"/>\n<userTask id=\"review\" flowable:collection=\"assignees\" flowable:elementVariable=\"assignee\"/>\n\n<!-- after: populate it first, or set it in the delegate -->\npublic void execute(DelegateExecution exec) {\n  exec.setVariable(\"assignees\", loadAssignees());\n}","handlingStrategy":"validation","validationCode":"// Check the variable exists before entering the multi-instance activity\nif (execution.getVariable(\"assignees\") == null) {\n    throw new IllegalStateException(\"Variable 'assignees' required by multi-instance activity must be set before this point\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.startProcessInstanceByKey(key, vars);\n} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().endsWith(\"was not found\")) {\n        // the flowable:collection variable was never set; fix upstream mapping\n    } else {\n        throw e;\n    }\n}","preventionTips":["Set the collection variable before the multi-instance activity (delegate, execution listener, or input mapping).","Double-check the exact variable name in flowable:collection (case-sensitive).","Verify call-activity in-mapping and service-task output mapping actually produce the variable.","Add an execution listener assertion that required variables exist at the activity entry."],"tags":["bpmn","process-engine","multi-instance","variables","process-design"],"backgroundTag":"missing-required-argument","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"}