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

  1. Set the collection variable before the multi-instance activity executes (delegate, listener, or input mapping).
  2. Verify the variable name in flowable:collection matches exactly the set variable (case-sensitive).
  3. Check call-activity in/out mappings and service-task output mappings that should produce the variable.
  4. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/d408306df50d67dd. Report an issue: GitHub.