flowable/flowable-engine · error · FlowableIllegalArgumentException
scopeContainer cannot be null
Error message
scopeContainer cannot be null
What it means
The CmmnVariableScopeResolver constructor throws FlowableIllegalArgumentException when scopeContainer is null. The resolver evaluates expressions against a scope (plan item instance or case instance); without a scope container there is nothing to resolve variables against, so construction fails fast.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/scripting/CmmnVariableScopeResolver.java:68
"cmmnManagementService", CmmnEngineConfiguration::getCmmnManagementService,
"taskService", CmmnEngineConfiguration::getCmmnTaskService,
"cmmnTaskService", CmmnEngineConfiguration::getCmmnTaskService
);
protected static final Set<String> KEYS = Set.of(
CASE_INSTANCE_KEY,
PLAN_ITEM_INSTANCE_KEY,
TASK_KEY
);
protected CmmnEngineConfiguration engineConfiguration;
protected VariableContainer scopeContainer;
protected VariableContainer inputVariableContainer;
public CmmnVariableScopeResolver(CmmnEngineConfiguration engineConfiguration, VariableContainer scopeContainer,
VariableContainer inputVariableContainer) {
if (scopeContainer == null) {
throw new FlowableIllegalArgumentException("scopeContainer cannot be null");
}
this.scopeContainer = scopeContainer;
this.inputVariableContainer = inputVariableContainer;
this.engineConfiguration = engineConfiguration;
}
@Override
public boolean containsKey(Object key) {
return inputVariableContainer.hasVariable((String) key) || KEYS.contains(key)
|| SERVICE_RESOLVERS.containsKey(key) && engineConfiguration.isServicesEnabledInScripting();
}
@Override
public Object get(Object key) {
if (SERVICE_RESOLVERS.containsKey((String) key)) {
if (engineConfiguration.isServicesEnabledInScripting()) {
return SERVICE_RESOLVERS.get(key).apply(engineConfiguration);
} else {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Ensure the scope container (plan item instance or case instance entity) is loaded before building the resolver.
- Pass the correct VariableContainer: use the plan item instance from the delegate context, not a null.
- If evaluating outside a case, use a different resolver/VariableScope rather than CmmnVariableScopeResolver with null.
Example fix
// before new CmmnVariableScopeResolver(config, null, inputContainer); // after VariableContainer scope = planItemInstance != null ? planItemInstance : caseInstance; new CmmnVariableScopeResolver(config, scope, inputContainer);
Defensive patterns
Strategy: type-guard
Validate before calling
if (scopeContainer == null) throw new IllegalStateException("Cannot resolve CMMN variables without a scope container"); Type guard
VariableContainer resolveScope(PlanItemInstance p, CaseInstance c) {
if (p != null) return p;
if (c != null) return c;
throw new IllegalStateException("No VariableContainer available");
} Try / catch
try { new CmmnVariableScopeResolver(config, scope, input); } catch (FlowableIllegalArgumentException e) { throw new IllegalStateException("scopeContainer missing for expression evaluation", e); } Prevention
- Always obtain the scope from the active delegate (DelegatePlanItemInstance/CaseInstance) rather than passing null.
- Do not instantiate the resolver outside a running case context.
When it happens
Trigger: Constructing CmmnVariableScopeResolver(engineConfiguration, null, inputVariableContainer) — usually when the calling delegate passes a null PlanItemInstanceEntity or CaseInstanceEntity into expression/script evaluation.
Common situations: Custom delegates or listeners evaluating expressions with a manually built scope that was never resolved; standalone scripting of CMMN expressions outside a running case; NPE-fix refactors that pass null through.
Related errors
- Case instance id is null
- Plan item instance id is null
- taskId is null
- caseInstanceId is required
- taskId is required
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/6133b74280a7d828.
Report an issue: GitHub.