{"record":{"id":"29e652c4f505731e","repo":"flowable/flowable-engine","slug":"could-not-resolve-loopcardinality-expression-lo","errorCode":null,"errorMessage":"Could not resolve loopCardinality expression '${loopCardinalityExpression.getExpressionText()}': not a number nor number String","messagePattern":"Could not resolve loopCardinality expression '(.+?)': not a number nor number String","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java","lineNumber":573,"sourceCode":"    protected boolean usesCollection() {\n        return collectionExpression != null || collectionVariable != null || collectionString != null;\n    }\n\n    protected boolean isExtraScopeNeeded(FlowNode flowNode) {\n        return flowNode.getSubProcess() != null;\n    }\n\n    protected int resolveLoopCardinality(DelegateExecution execution) {\n        // Using Number since expr can evaluate to eg. Long (which is also the default for Juel)\n        Object value = loopCardinalityExpression.getValue(execution);\n        if (value instanceof Number) {\n            return ((Number) value).intValue();\n\n        } else if (value instanceof String) {\n            return Integer.valueOf((String) value);\n\n        } else {\n            throw new FlowableIllegalArgumentException(\"Could not resolve loopCardinality expression '\" + loopCardinalityExpression.getExpressionText() + \"': not a number nor number String\");\n        }\n    }\n\n    protected void setLoopVariable(DelegateExecution execution, String variableName, Object value) {\n        execution.setVariableLocal(variableName, value);\n    }\n\n    protected Integer getLocalLoopVariable(DelegateExecution execution, String variableName) {\n        Map<String, Object> localVariables = execution.getVariablesLocal();\n        if (localVariables.containsKey(variableName)) {\n            return (Integer) execution.getVariableLocal(variableName);\n            \n        } else if (!execution.isMultiInstanceRoot()) {\n            DelegateExecution parentExecution = execution.getParent();\n            localVariables = parentExecution.getVariablesLocal();\n            if (localVariables.containsKey(variableName)) {\n                return (Integer) parentExecution.getVariableLocal(variableName);\n                ","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java#L555-L591","documentation":"Thrown when parsing the loopCardinality of a multi-instance activity: the loopCardinalityExpression evaluated to a value that is neither a Number nor a String parsable as an integer, so resolveNumberOfInstances cannot compute the instance count. The message includes the expression text so you can identify the failing condition.","triggerScenarios":"<multiInstanceLoopCharacteristics><loopCardinality>${expr}</loopCardinality> where expr evaluates to null, a Boolean, a non-numeric String like 'three', or an object; also Integer.valueOf failing on strings with spaces or decimals.","commonSituations":"loopCardinality pointing at an unset (null) variable; variable holding '3.5' or '3 ' (non-parseable string); expression returning a Long/BigInteger path is fine but a custom object or boolean is returned; copy-paste of an expression referencing the wrong variable.","solutions":["Make the expression evaluate to a Number or an integer String, e.g. loopCardinality=3 or ${nrOfItems} with nrOfItems being an Integer.","Initialize the referenced variable with an Integer value before the activity executes.","Strip formatting from numeric strings ('3 ' or '3.0' will not parse) and store plain integers.","Change a boolean/wrong-typed variable to the intended count variable.","Validate the cardinality expression in a unit test before deploying."],"exampleFix":"// before\nvars.put(\"nrOfApprovers\", \"three\");\n// after\nvars.put(\"nrOfApprovers\", 3);","handlingStrategy":"validation","validationCode":"Object c = execution.getVariable(\"nrOfApprovers\");\nboolean ok = (c instanceof Number) || (c instanceof String && c.toString().trim().matches(\"\\\\d+\"));\nif (!ok) throw new IllegalStateException(\"loopCardinality value must be a number or numeric string, got: \" + c);","typeGuard":"boolean isCardinalityValue(Object v) {\n    return v instanceof Number || (v instanceof String && ((String) v).trim().matches(\"\\\\d+\"));\n}","tryCatchPattern":"try {\n    return task.execute(execution);\n} catch (FlowableIllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"loopCardinality\")) {\n        logger.error(\"Invalid loopCardinality expression result: {}\", ex.getMessage());\n    }\n    throw ex;\n}","preventionTips":["Store cardinality variables as Integer, not formatted strings.","Avoid decimal/whitespace-laden numeric strings ('3.0', '3 ').","Keep loopCardinality expressions pointing at dedicated count variables.","Unit-test cardinality expressions with representative variable values."],"tags":["bpmn","multi-instance","loop-cardinality","expression"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}