flowable/flowable-engine · error · FlowableIllegalArgumentException
variables is empty
Error message
variables is empty
What it means
SetLocalVariablesCmd.execute() throws FlowableIllegalArgumentException when the variables map is empty (after null checks on id and map). The engine refuses to execute a variable-set command that would change nothing.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/SetLocalVariablesCmd.java:46
protected String planItemInstanceId;
protected Map<String, Object> variables;
public SetLocalVariablesCmd(String planItemInstanceId, Map<String, Object> variables) {
this.planItemInstanceId = planItemInstanceId;
this.variables = variables;
}
@Override
public Void execute(CommandContext commandContext) {
if (planItemInstanceId == null) {
throw new FlowableIllegalArgumentException("planItemInstanceId is null");
}
if (variables == null) {
throw new FlowableIllegalArgumentException("variables is null");
}
if (variables.isEmpty()) {
throw new FlowableIllegalArgumentException("variables is empty");
}
PlanItemInstanceEntity planItemInstanceEntity = CommandContextUtil.getPlanItemInstanceEntityManager(commandContext).findById(planItemInstanceId);
if (planItemInstanceEntity == null) {
throw new FlowableObjectNotFoundException("No plan item instance found for id " + planItemInstanceId, PlanItemInstanceEntity.class);
}
planItemInstanceEntity.setVariablesLocal(variables);
CommandContextUtil.getAgenda(commandContext).planEvaluateCriteriaOperation(planItemInstanceEntity.getCaseInstanceId());
return null;
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Guard the call with !variables.isEmpty() and skip it when there is nothing to set.
- Only build/submit the command when at least one variable needs to be written.
- If a no-op is intended, simply do not call the API.
Example fix
// before
cmmnRuntimeService.setLocalVariables(planItemId, applicableVars); // may be empty
// after
if (!applicableVars.isEmpty()) {
cmmnRuntimeService.setLocalVariables(planItemId, applicableVars);
} Defensive patterns
Strategy: validation
Validate before calling
if (variables == null || variables.isEmpty()) {
return; // nothing to set
} Type guard
boolean isNonEmpty(Map<String, ?> m) { return m != null && !m.isEmpty(); } Try / catch
try {
cmmnRuntimeService.setLocalVariables(planItemId, vars);
} catch (FlowableIllegalArgumentException e) {
log.error("setLocalVariables rejected: {}", e.getMessage());
} Prevention
- Guard all variable-set calls with a non-empty check.
- Avoid unconditional calls in loops; compute applicability first.
- Cover empty-delta cases in unit tests.
When it happens
Trigger: Calling CmmnRuntimeService.setLocalVariables(planItemInstanceId, new HashMap<>()) or with a map whose entries were all filtered out before the call.
Common situations: Computed delta maps ending up empty; loops that unconditionally invoke the setter per plan item even when no variable applies to that one.
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
- variables is empty
- variables is empty
- variables is empty
- Could not find an app definition with id '<appDefinitionId>
- Could not find a deployment with id '<deploymentId>
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/bec859705ca92f7c.
Report an issue: GitHub.