flowable/flowable-engine · error · FlowableIllegalArgumentException

variables is null

Error message

variables is null

What it means

Thrown by SetVariablesAsyncCmd.execute when the variables map is null. After checking the case instance id, the command validates the variables argument; null maps are rejected with FlowableIllegalArgumentException since there is nothing to schedule for the async job.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/SetVariablesAsyncCmd.java:41

import org.flowable.common.engine.impl.interceptor.CommandContext;

public class SetVariablesAsyncCmd extends AbstractSetVariableAsyncCmd implements Command<Void> {
    
    protected String caseInstanceId;
    protected Map<String, Object> variables;
    
    public SetVariablesAsyncCmd(String caseInstanceId, Map<String, Object> variables) {
        this.caseInstanceId = caseInstanceId;
        this.variables = variables;
    }
    
    @Override
    public Void execute(CommandContext commandContext) {
        if (caseInstanceId == null) {
            throw new FlowableIllegalArgumentException("caseInstanceId is null");
        }
        if (variables == null) {
            throw new FlowableIllegalArgumentException("variables is null");
        }
        if (variables.isEmpty()) {
            throw new FlowableIllegalArgumentException("variables is empty");
        }
     
        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        CaseInstanceEntity caseInstanceEntity = cmmnEngineConfiguration.getCaseInstanceEntityManager().findById(caseInstanceId);
        if (caseInstanceEntity == null) {
            throw new FlowableObjectNotFoundException("No case instance found for id " + caseInstanceId, CaseInstanceEntity.class);
        }
        
        for (String variableName : variables.keySet()) {
            addVariable(false, caseInstanceId, null, variableName, variables.get(variableName), caseInstanceEntity.getTenantId(), 
                    cmmnEngineConfiguration.getVariableServiceConfiguration().getVariableService());
        }
        
        createSetAsyncVariablesJob(caseInstanceEntity, cmmnEngineConfiguration);
        

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a non-null map (even an empty one if allowed, but note empty also throws)
  2. Initialize the variables map before the call
  3. Fix the deserialization/binding that produced null

Example fix

// before
cmmnRuntimeService.setVariablesAsync(caseId, vars); // vars may be null
// after
Map<String, Object> vars = payload.getVars();
if (vars == null || vars.isEmpty()) throw new IllegalArgumentException("variables required");
cmmnRuntimeService.setVariablesAsync(caseId, vars);
Defensive patterns

Strategy: validation

Validate before calling

if (variables == null || variables.isEmpty()) {
    throw new IllegalArgumentException("variables map must be non-null and non-empty");
}

Type guard

boolean hasVariables(Map<String, Object> vars) { return vars != null && !vars.isEmpty(); }

Try / catch

try {
    cmmnRuntimeService.setVariablesAsync(caseInstanceId, vars);
} catch (FlowableIllegalArgumentException e) {
    log.error("Invalid variables argument: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling setVariablesAsync(caseInstanceId, null) or passing a map field never initialized.

Common situations: Deserialization of an empty/absent JSON payload yielding null, refactoring left the map unassigned.

Related errors


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