flowable/flowable-engine · error · ActivitiIllegalArgumentException

Invalid number of instances: must be a non-negative integer

Error message

Invalid number of instances: must be a non-negative integer value, but was ${nrOfInstances}

What it means

Thrown by SequentialMultiInstanceBehavior.createInstances when the resolved number of instances for a sequential multi-instance activity is negative. The engine requires nrOfInstances to be a non-negative integer before it can initialize loop variables (loopCounter, nrOfCompletedInstances). This almost always means the loopCardinality expression or collection-based cardinality resolved to a bad value.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/SequentialMultiInstanceBehavior.java:40

/**
 * @author Joram Barrez
 * @author Falko Menge
 */
public class SequentialMultiInstanceBehavior extends MultiInstanceActivityBehavior {

    public SequentialMultiInstanceBehavior(ActivityImpl activity, ActivityBehavior innerActivityBehavior) {
        super(activity, innerActivityBehavior);
    }

    /**
     * Handles the sequential case of spawning the instances. Will only create one instance, since at most one instance can be active.
     */
    @Override
    protected void createInstances(ActivityExecution execution) {
        int nrOfInstances = resolveNrOfInstances(execution);
        if (nrOfInstances < 0) {
            throw new ActivitiIllegalArgumentException("Invalid number of instances: must be a non-negative integer value"
                    + ", but was " + nrOfInstances);
        }

        setLoopVariable(execution, NUMBER_OF_INSTANCES, nrOfInstances);
        setLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES, 0);
        setLoopVariable(execution, getCollectionElementIndexVariable(), 0);
        setLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES, 1);
        logLoopDetails(execution, "initialized", 0, 0, 1, nrOfInstances);

        if (nrOfInstances > 0) {
            executeOriginalBehavior(execution, 0);
        }
    }

    /**
     * Called when the wrapped {@link ActivityBehavior} calls the {@link AbstractBpmnActivityBehavior#leave(ActivityExecution)} method. Handles the completion of one instance, and executes the logic
     * for the sequential behavior.
     */

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set a valid loopCardinality (non-negative int) or a collection on the multiInstanceLoopCharacteristics of the activity
  2. Check the expression/variable used for cardinality at runtime and ensure the process variable exists and is >= 0
  3. Log or assert the resolved value before the multi-instance activity (e.g. a listener or script task) to find where the negative value originates
  4. If using a collection, verify the collection expression resolves to a real Collection bean/variable, not null

Example fix

// before (BPMN)
<multiInstanceLoopCharacteristics isSequential="true">
  <loopCardinality>${nrOfApprovers - 1}</loopCardinality>
</multiInstanceLoopCharacteristics>
// after
<multiInstanceLoopCharacteristics isSequential="true">
  <loopCardinality>${approvedCount}</loopCardinality>
</multiInstanceLoopCharacteristics>
<!-- plus a guard: if (approvedCount < 0) approvedCount = 0; -->
Defensive patterns

Strategy: validation

Validate before calling

Object v = execution.getVariable("approvedCount");
int nr = v instanceof Number ? ((Number) v).intValue() : -1;
if (nr < 0) {
    throw new IllegalArgumentException("approvedCount must be >= 0, was " + nr);
}

Type guard

public static boolean isNonNegativeInt(Object v) {
    return v instanceof Number && ((Number) v).intValue() >= 0;
}

Try / catch

try {
    runtimeService.startProcessInstanceByKey(key, vars);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("Invalid number of instances")) {
        // fix cardinality/variable and retry with sanitized value
    } else { throw e; }
}

Prevention

When it happens

Trigger: A multi-instance activity with loopCardinality evaluated to a negative number (e.g. an expression like ${count - 5} yielding -2), or resolveNrOfInstances returning -1 because neither loopCardinality nor a collection was configured on the multi-instance activity.

Common situations: Missing loopCardinality/collectionDefinition on multiInstanceLoopCharacteristics in the BPMN XML; a process variable used in the cardinality expression is unset or negative; a collection-resolved count computed as negative during script/delegate logic; copying a process definition from another engine with different loop-variable semantics.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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