{"record":{"id":"bc23af617f4b3b0a","repo":"flowable/flowable-engine","slug":"variable-obj-collectionvariable-is-not-a-c","errorCode":null,"errorMessage":"Variable '${obj}':${collectionVariable} is not a Collection","messagePattern":"Variable '(.+?)':(.+?) is not a Collection","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java","lineNumber":503,"sourceCode":"        if (collectionHandler != null ) {           \n            return createFlowableCollectionHandler(collectionHandler, execution).resolveCollection(obj, execution);\n        } else {\n            if (obj instanceof Collection) {\n                return (Collection) obj;\n                \n            } else if (obj instanceof Iterable) {\n                return iterableToCollection((Iterable) obj);\n                \n            } else if (obj instanceof String) {\n                Object collectionVariable = execution.getVariable((String) obj);\n                if (collectionVariable instanceof Collection) {\n                    return (Collection) collectionVariable;\n                } else if (collectionVariable instanceof Iterable) {\n                    return iterableToCollection((Iterable) collectionVariable);\n                } else if (collectionVariable == null) {\n                    throw new FlowableIllegalArgumentException(\"Variable '\" + obj + \"' was not found\");\n                } else {\n                    throw new FlowableIllegalArgumentException(\"Variable '\" + obj + \"':\" + collectionVariable + \" is not a Collection\");\n                }\n                \n            } else {\n                throw new FlowableIllegalArgumentException(buildUnresolvedCollectionExceptionMessage());\n            }\n        }\n    }\n\n    protected String buildUnresolvedCollectionExceptionMessage() {\n        StringBuilder exceptionStringBuilder = new StringBuilder(\"Couldn't resolve collection expression\");\n        if (collectionExpression != null) {\n            exceptionStringBuilder.append(\" (\");\n            exceptionStringBuilder.append(collectionExpression.getExpressionText());\n            exceptionStringBuilder.append(\")\");\n        }\n        exceptionStringBuilder.append(\", variable reference\");\n        if (collectionVariable != null) {\n            exceptionStringBuilder.append(\" (\");","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java#L485-L521","documentation":"Thrown by MultiInstanceActivityBehavior.resolveAndValidateCollection when the configured collection variable exists but its value is neither a Collection nor an Iterable. The message reports the variable name ('${obj}') and the offending value so you can see what type was actually stored.","triggerScenarios":"flowable:collection=\"assigneeList\" where 'assigneeList' is present in the execution but holds e.g. a String, Map, array, single object, or Integer instead of a List/Set (or other Iterable).","commonSituations":"Variable set to a comma-separated String instead of a List; array (String[]) set where Flowable expects a Collection/Iterable; variable overwritten later in the process with a scalar; JSON deserialization storing a Map instead of a List; Groovy/JS expression returning a non-collection value.","solutions":["Store a java.util.Collection (List/Set) in the variable, e.g. Arrays.asList(\"a\",\"b\").","Convert arrays or strings to a Collection before setting the variable.","Check where the variable is overwritten downstream and fix the conflicting assignment.","If it is a Map of items, store map.values() or the relevant entry instead of the Map itself.","Log the variable type (runtimeService.getVariable) to confirm what is actually stored."],"exampleFix":"// before\nvars.put(\"assigneeList\", \"kermit,gonzo\");\n// after\nvars.put(\"assigneeList\", Arrays.asList(\"kermit\", \"gonzo\"));","handlingStrategy":"type-guard","validationCode":"Object v = execution.getVariable(\"assigneeList\");\nif (v != null && !(v instanceof Collection) && !(v instanceof Iterable)) {\n    throw new IllegalStateException(\"assigneeList must be a Collection/Iterable, got: \" + v.getClass());\n}","typeGuard":"boolean isCollection(Object v) {\n    return v instanceof Collection || v instanceof Iterable;\n}","tryCatchPattern":"try {\n    return task.execute(execution);\n} catch (FlowableIllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"is not a Collection\")) {\n        logger.error(\"Wrong variable type for multi-instance collection: {}\", ex.getMessage());\n    }\n    throw ex;\n}","preventionTips":["Store List/Set (Collection or Iterable) in collection variables, never String/Map/array.","Convert comma-separated strings via split and Arrays.asList before storing.","Audit variable writers to ensure no downstream code overwrites with a scalar.","Log variable types at set-time in dev environments to catch type drift early."],"tags":["bpmn","multi-instance","collection","type-mismatch"],"backgroundTag":"type-mismatch","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"}