flowable/flowable-engine · error · FlowableIllegalArgumentException
Variable '${obj}' was not found
Error message
Variable '${obj}' was not found What it means
Thrown by MultiInstanceActivityBehavior.resolveAndValidateCollection when the configured collection attribute names a process variable that does not exist in the execution: execution.getVariable(obj) returns null, so the behavior cannot build the list of multi-instance elements. The '${obj}' in the message is the variable name taken from the collection configuration.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java:501
protected Collection resolveAndValidateCollection(DelegateExecution execution) {
Object obj = resolveCollection(execution);
if (collectionHandler != null ) {
return createFlowableCollectionHandler(collectionHandler, execution).resolveCollection(obj, execution);
} else {
if (obj instanceof Collection) {
return (Collection) obj;
} else if (obj instanceof Iterable) {
return iterableToCollection((Iterable) obj);
} else if (obj instanceof String) {
Object collectionVariable = execution.getVariable((String) obj);
if (collectionVariable instanceof Collection) {
return (Collection) collectionVariable;
} else if (collectionVariable instanceof Iterable) {
return iterableToCollection((Iterable) collectionVariable);
} else if (collectionVariable == null) {
throw new FlowableIllegalArgumentException("Variable '" + obj + "' was not found");
} else {
throw new FlowableIllegalArgumentException("Variable '" + obj + "':" + collectionVariable + " is not a Collection");
}
} else {
throw new FlowableIllegalArgumentException(buildUnresolvedCollectionExceptionMessage());
}
}
}
protected String buildUnresolvedCollectionExceptionMessage() {
StringBuilder exceptionStringBuilder = new StringBuilder("Couldn't resolve collection expression");
if (collectionExpression != null) {
exceptionStringBuilder.append(" (");
exceptionStringBuilder.append(collectionExpression.getExpressionText());
exceptionStringBuilder.append(")");
}
exceptionStringBuilder.append(", variable reference");View on GitHub (pinned to d6d39ce1c6)
Solutions
- Set the collection variable before the multi-instance activity runs, e.g. pass it in the process start variables map.
- Correct the variable name in the flowable:collection attribute to match the actual variable.
- Initialize the variable in a start listener or a preceding service task if it is derived at runtime.
- Add a guard service task that checks the variable exists and fails early with a clearer message.
- Use a collection expression resolving to a default empty list if zero instances is acceptable.
Example fix
// before
runtimeService.startProcessInstanceByKey("orderProcess");
// after: provide the collection variable expected by flowable:collection="assigneeList"
Map<String, Object> vars = new HashMap<>();
vars.put("assigneeList", List.of("kermit", "gonzo"));
runtimeService.startProcessInstanceByKey("orderProcess", vars); Defensive patterns
Strategy: validation
Validate before calling
Map<String, Object> vars = new HashMap<>();
vars.put("assigneeList", java.util.Arrays.asList("kermit", "gonzo")); // must be present & non-null before the activity
runtimeService.startProcessInstanceByKey("orderProcess", vars); Type guard
boolean validCollection(Object v) { return v instanceof Collection || v instanceof Iterable; } Try / catch
try {
runtimeService.trigger(executionId);
} catch (FlowableIllegalArgumentException ex) {
if (ex.getMessage().contains("was not found")) {
logger.error("Missing collection variable: {}", ex.getMessage());
}
throw ex;
} Prevention
- Pass collection variables explicitly at process start or set them in an init task.
- Standardize variable names as constants to avoid typos.
- Set variables on the correct (root) scope so child executions inherit them.
- Add a guard task/listener that fails fast when required variables are absent.
When it happens
Trigger: flowable:collection="assigneeList" on a multi-instance activity where process variable 'assigneeList' was never set (or was removed / set with a different name / not visible on this scope) before the multi-instance behavior executes.
Common situations: Caller forgot to pass the collection variable when starting the process (runtimeService.startProcessInstanceByKey(vars)); variable set under a different name or with a typo; variable set only on a child scope that has ended; race where the variable is set asynchronously after the task is reached.
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
- Couldn't resolve collection expression nor variable referenc
- Variable '${obj}':${collectionVariable} is not a Collection
- Couldn't resolve collection expression${collectionExpression
- Expected an activity behavior in flow node ${flowNode.getId(
- completionCondition '${activeCompletionCondition}' does not
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b498964789413168.
Report an issue: GitHub.