flowable/flowable-engine · error · FlowableIllegalArgumentException
variables is empty
Error message
variables is empty
What it means
Thrown by SetVariablesAsyncCmd.execute when the variables map is non-null but empty. The command requires at least one variable to write, so an empty map is rejected with FlowableIllegalArgumentException to avoid scheduling a pointless async job.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/SetVariablesAsyncCmd.java:44
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);
return null;
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Skip the call when the map is empty instead of invoking the API
- Validate map non-empty before calling and fail earlier with a clearer message
- Fix the upstream collection building so it produces the expected entries
Example fix
// before
if (!vars.isEmpty()) {
cmmnRuntimeService.setVariablesAsync(caseId, vars);
}
// after (explicit guard at the API boundary)
if (vars == null || vars.isEmpty()) {
throw new IllegalArgumentException("At least one variable is required");
}
cmmnRuntimeService.setVariablesAsync(caseId, vars); Defensive patterns
Strategy: validation
Validate before calling
if (variables == null || variables.isEmpty()) {
throw new IllegalArgumentException("At least one variable is required");
} 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("No variables provided: {}", e.getMessage());
} Prevention
- Skip the engine call entirely when there is nothing to set
- Log/review filtering logic that can drain the map to zero entries
- Add early guards in batch jobs so empty updates fail before job scheduling
When it happens
Trigger: Calling setVariablesAsync with an empty Map, typically from a filtered/transformed collection that ended up with zero entries.
Common situations: Input payload with no variables, all entries filtered out by validation logic, batch job iterating over cases with nothing to set.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Could not find an app definition with id '<appDefinitionId>
- Could not find a deployment with id '<deploymentId>
- Empty appsDefinitionIds
- ids is an empty collection
- type is required when adding a new case instance identity li
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/63ea2d602e3b718a.
Report an issue: GitHub.