flowable/flowable-engine · error · FlowableIllegalArgumentException

Couldn't resolve collection expression${collectionExpression

Error message

Couldn't resolve collection expression${collectionExpression details}

What it means

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.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java:507

                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");
        if (collectionVariable != null) {
            exceptionStringBuilder.append(" (");
            exceptionStringBuilder.append(collectionVariable);
            exceptionStringBuilder.append(")");
        }
        exceptionStringBuilder.append(" or string");

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Fix the expression so it evaluates to a Collection/Iterable, e.g. '${userService.getAssignees(execution)}' returning List.
  2. Null-check/initialize the underlying variables or bean results before the activity executes.
  3. Convert arrays to List at the source (Arrays.asList) since arrays are not Collections.
  4. Verify the bean used in the expression is registered in the process engine configuration beans map.
  5. Test the expression in isolation (e.g. in a small unit test with the expression manager) to see its actual value.

Example fix

// before: bean returns an array
public String[] getAssignees() { ... }
// after: return a Collection
public List<String> getAssignees() { return Arrays.asList("kermit", "gonzo"); }
Defensive patterns

Strategy: validation

Validate before calling

Object resolved = expressionManager.createExpression("${userService.getAssignees(execution)}").getValue(execution);
if (!(resolved instanceof Collection)) {
    throw new IllegalStateException("collection expression must yield a Collection, got: "
        + (resolved == null ? "null" : resolved.getClass().getName()));
}

Try / catch

try {
    return task.execute(execution);
} catch (FlowableIllegalArgumentException ex) {
    if (ex.getMessage().startsWith("Couldn't resolve collection expression")) {
        logger.error("Collection expression returned non-collection: {}", ex.getMessage());
    }
    throw ex;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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