{"record":{"id":"b498964789413168","repo":"flowable/flowable-engine","slug":"variable-obj-was-not-found","errorCode":null,"errorMessage":"Variable '${obj}' was not found","messagePattern":"Variable '(.+?)' was not found","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java","lineNumber":501,"sourceCode":"    protected Collection resolveAndValidateCollection(DelegateExecution execution) {\n        Object obj = resolveCollection(execution);\n        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\");","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java#L483-L519","documentation":"Thrown by MultiInstanceActivityBehavior.resolveAndValidateCollection when the configured collection attribute names a process variable that does not exist in the execution: execution.getVariable(obj) returns null, so the behavior cannot build the list of multi-instance elements. The '${obj}' in the message is the variable name taken from the collection configuration.","triggerScenarios":"flowable:collection=\"assigneeList\" on a multi-instance activity where process variable 'assigneeList' was never set (or was removed / set with a different name / not visible on this scope) before the multi-instance behavior executes.","commonSituations":"Caller forgot to pass the collection variable when starting the process (runtimeService.startProcessInstanceByKey(vars)); variable set under a different name or with a typo; variable set only on a child scope that has ended; race where the variable is set asynchronously after the task is reached.","solutions":["Set the collection variable before the multi-instance activity runs, e.g. pass it in the process start variables map.","Correct the variable name in the flowable:collection attribute to match the actual variable.","Initialize the variable in a start listener or a preceding service task if it is derived at runtime.","Add a guard service task that checks the variable exists and fails early with a clearer message.","Use a collection expression resolving to a default empty list if zero instances is acceptable."],"exampleFix":"// before\nruntimeService.startProcessInstanceByKey(\"orderProcess\");\n// after: provide the collection variable expected by flowable:collection=\"assigneeList\"\nMap<String, Object> vars = new HashMap<>();\nvars.put(\"assigneeList\", List.of(\"kermit\", \"gonzo\"));\nruntimeService.startProcessInstanceByKey(\"orderProcess\", vars);","handlingStrategy":"validation","validationCode":"Map<String, Object> vars = new HashMap<>();\nvars.put(\"assigneeList\", java.util.Arrays.asList(\"kermit\", \"gonzo\")); // must be present & non-null before the activity\nruntimeService.startProcessInstanceByKey(\"orderProcess\", vars);","typeGuard":"boolean validCollection(Object v) { return v instanceof Collection || v instanceof Iterable; }","tryCatchPattern":"try {\n    runtimeService.trigger(executionId);\n} catch (FlowableIllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"was not found\")) {\n        logger.error(\"Missing collection variable: {}\", ex.getMessage());\n    }\n    throw ex;\n}","preventionTips":["Pass collection variables explicitly at process start or set them in an init task.","Standardize variable names as constants to avoid typos.","Set variables on the correct (root) scope so child executions inherit them.","Add a guard task/listener that fails fast when required variables are absent."],"tags":["bpmn","multi-instance","process-variables","collection"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}