flowable/flowable-engine · error · ActivitiIllegalArgumentException
Variable ${collectionVariable} was not found
Error message
Variable ${collectionVariable} was not found What it means
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.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java:149
}
// Helpers //////////////////////////////////////////////////////////////////////
@SuppressWarnings("rawtypes")
protected int resolveNrOfInstances(ActivityExecution execution) {
int nrOfInstances = -1;
if (loopCardinalityExpression != null) {
nrOfInstances = resolveLoopCardinality(execution);
} else if (collectionExpression != null) {
Object obj = collectionExpression.getValue(execution);
if (!(obj instanceof Collection)) {
throw new ActivitiIllegalArgumentException(collectionExpression.getExpressionText() + "' didn't resolve to a Collection");
}
nrOfInstances = ((Collection) obj).size();
} else if (collectionVariable != null) {
Object obj = execution.getVariable(collectionVariable);
if (obj == null) {
throw new ActivitiIllegalArgumentException("Variable " + collectionVariable + " was not found");
}
if (!(obj instanceof Collection)) {
throw new ActivitiIllegalArgumentException("Variable " + collectionVariable + "' is not a Collection");
}
nrOfInstances = ((Collection) obj).size();
} else {
throw new ActivitiIllegalArgumentException("Couldn't resolve collection expression nor variable reference");
}
return nrOfInstances;
}
@SuppressWarnings("rawtypes")
protected void executeOriginalBehavior(ActivityExecution execution, int loopCounter) {
if (usesCollection() && collectionElementVariable != null) {
Collection collection = null;
if (collectionExpression != null) {
collection = (Collection) collectionExpression.getValue(execution);
} else if (collectionVariable != null) {View on GitHub (pinned to d6d39ce1c6)
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.
Example fix
<!-- before: variable 'assignees' is never created -->
<serviceTask id="fetch" flowable:delegateExpression="${fetcher}"/>
<userTask id="review" flowable:collection="assignees" flowable:elementVariable="assignee"/>
<!-- after: populate it first, or set it in the delegate -->
public void execute(DelegateExecution exec) {
exec.setVariable("assignees", loadAssignees());
} Defensive patterns
Strategy: validation
Validate before calling
// Check the variable exists before entering the multi-instance activity
if (execution.getVariable("assignees") == null) {
throw new IllegalStateException("Variable 'assignees' required by multi-instance activity must be set before this point");
} Try / catch
try {
runtimeService.startProcessInstanceByKey(key, vars);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().endsWith("was not found")) {
// the flowable:collection variable was never set; fix upstream mapping
} else {
throw e;
}
} Prevention
- 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.
When it happens
Trigger: flowable:collection="assignees" on a multi-instance task where variable 'assignees' was never set (or was removed) before the multi-instance activity starts.
Common situations: 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.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Variable ${collectionVariable}' is not a Collection
- No outgoing sequence flow of the inclusive gateway '${activi
- Not supported to signal this execution
- ${collectionExpressionText}' didn't resolve to a Collection
- Expected an activity behavior in flow node ${flowNode.getId(
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d408306df50d67dd.
Report an issue: GitHub.