flowable/flowable-engine · error · FlowableIllegalArgumentException
Could not evaluate collection for repetition rule on plan it
Error message
Could not evaluate collection for repetition rule on plan item with id '${planItemInstanceEntity.getId()}', collection variable name '${repetitionRule.getCollectionVariableName()}' evaluated to '${collection}', but needs to be a collection, an iterable or an ArrayNode (JSON). What it means
ExpressionUtil.evaluateRepetitionCollectionVariableValue resolves the repetition rule's collection variable and accepts only Collection, Iterable, or JSON ArrayNode values. Any other type (String, Map handled elsewhere?, scalar, null beyond the earlier guard) causes this FlowableIllegalArgumentException, since multi-instance/repetition requires something iterable to create plan item instances from.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/util/ExpressionUtil.java:168
return null;
}
String collectionExpression = repetitionRule.getCollectionVariableName();
if (!(collectionExpression.startsWith("${") || collectionExpression.startsWith("#{"))) {
collectionExpression = "${vars:getOrDefault('" + collectionExpression + "', null)}";
}
Object collection = evaluateExpression(commandContext, planItemInstanceEntity, collectionExpression);
if (collection == null) {
return null;
}
if (collection instanceof Iterable) {
return (Iterable<Object>) collection;
}
throw new FlowableIllegalArgumentException("Could not evaluate collection for repetition rule on plan item with id '" + planItemInstanceEntity.getId() +
"', collection variable name '" + repetitionRule.getCollectionVariableName() + "' evaluated to '" + collection +
"', but needs to be a collection, an iterable or an ArrayNode (JSON).");
}
/**
* Returns true, if: the given plan item instance has a repetition rule at all and if so, if it has a condition witch is satisfied and all in combination
* with the optional max instance count attribute. If the repetition rule evaluates to true, this normally means that there should be an additional
* instance of the plan item created.
*
* @param commandContext the command context in which this evaluation is taking place
* @param planItemInstanceEntity the plan item instance entity to test for a repetition rule to evaluate to true
* @param planItemInstanceContainer the container (usually the parent stage of the plan item instance) to get access to child plan items
* @return true, if there is a repetition rule of the plan item instance currently evaluating to true with all of its conditions and attributes
*/
public static boolean evaluateRepetitionRule(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity,
PlanItemInstanceContainer planItemInstanceContainer) {
RepetitionRule repetitionRule = getRepetitionRule(planItemInstanceEntity);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Set the collection variable to a java.util.Collection/List, an Iterable, or a com.fasterxml.jackson.databind.node.ArrayNode
- If the source data is a delimited String, split it first: Arrays.asList(csv.split(",")) and store that as the variable
- Ensure the JSON payload is parsed as an ArrayNode (e.g. objectMapper.readTree returning an array) not a scalar/object
- Add a check/log of the variable's type at runtime to catch upstream overwrites
Example fix
// before
execution.setVariable("items", "item1,item2");
// after
execution.setVariable("items", Arrays.asList("item1", "item2")); Defensive patterns
Strategy: validation
Validate before calling
Object collection = variableContainer.getVariable(repetitionRule.getCollectionVariableName());
if (!(collection instanceof Collection) && !(collection instanceof Iterable) && !(collection instanceof ArrayNode)) {
throw new IllegalStateException("Repetition collection variable '" + repetitionRule.getCollectionVariableName() + "' must be Collection/Iterable/ArrayNode, got: " + (collection == null ? "null" : collection.getClass()));
} Type guard
boolean isRepetitionCollection(Object v) { return v instanceof Iterable || v instanceof ArrayNode; } Try / catch
try { evaluateRepetition(); } catch (FlowableIllegalArgumentException e) { if (e.getMessage().contains("repetition rule")) { log.error("Collection variable '{}' has wrong type", repetitionRule.getCollectionVariableName()); throw e; } throw e; } Prevention
- Store repetition collections as List/Set or JSON ArrayNode only
- Split delimited strings into lists before assigning to collection variables
- Watch for later overwrites that change the variable's type
When it happens
Trigger: A plan item has a repetition rule with a collectionVariableName whose variable resolves to a non-iterable value — e.g. a comma-separated String like 'a,b,c', a single object, or a number — when the engine evaluates the repetition rule at plan item creation.
Common situations: Storing CSV strings in a variable and pointing collectionVariableName at them; a variable overwritten by later logic from a List to a scalar; JSON returned as an ObjectNode rather than ArrayNode; type changes after a model refactor.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Deployment ids is null
- Invalid usage of async_activate job handler, variable scope
- Invalid usage of ${TYPE} job handler, variable scope is of t
- Delegate expression ${expression} did not resolve to an impl
- Delegate expression ${expression} did not resolve to an impl
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1f86d05e1fc30ddd.
Report an issue: GitHub.