{"record":{"id":"19fb26d96118b610","repo":"flowable/flowable-engine","slug":"variables-is-empty","errorCode":null,"errorMessage":"variables is empty","messagePattern":"variables is empty","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/SetLocalVariablesAsyncCmd.java","lineNumber":44,"sourceCode":"    \n    protected String planItemInstanceId;\n    protected Map<String, Object> variables;\n    \n    public SetLocalVariablesAsyncCmd(String planItemInstanceId, Map<String, Object> variables) {\n        this.planItemInstanceId = planItemInstanceId;\n        this.variables = variables;\n    }\n    \n    @Override\n    public Void execute(CommandContext commandContext) {\n        if (planItemInstanceId == null) {\n            throw new FlowableIllegalArgumentException(\"planItemInstanceId is null\");\n        }\n        if (variables == null) {\n            throw new FlowableIllegalArgumentException(\"variables is null\");\n        }\n        if (variables.isEmpty()) {\n            throw new FlowableIllegalArgumentException(\"variables is empty\");\n        }\n     \n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        PlanItemInstanceEntity planItemInstanceEntity = cmmnEngineConfiguration.getPlanItemInstanceEntityManager().findById(planItemInstanceId);\n        if (planItemInstanceEntity == null) {\n            throw new FlowableObjectNotFoundException(\"No plan item instance found for id \" + planItemInstanceId, PlanItemInstanceEntity.class);\n        }\n        \n        for (String variableName : variables.keySet()) {\n            addVariable(true, planItemInstanceEntity.getCaseInstanceId(), planItemInstanceEntity.getId(), variableName, variables.get(variableName), \n                    planItemInstanceEntity.getTenantId(), cmmnEngineConfiguration.getVariableServiceConfiguration().getVariableService());\n        }\n        \n        createSetAsyncVariablesJob(planItemInstanceEntity, cmmnEngineConfiguration);\n        \n        return null;\n    }\n","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/SetLocalVariablesAsyncCmd.java#L26-L62","documentation":"SetLocalVariablesAsyncCmd.execute() throws FlowableIllegalArgumentException when the variables map is empty. An empty map would produce no work, so the engine treats it as invalid input rather than scheduling a pointless async job.","triggerScenarios":"Calling CmmnRuntimeService.setLocalVariablesAsync(planItemInstanceId, Collections.emptyMap()) or with a map filtered down to zero entries before the call.","commonSituations":"Batch code that computes variable deltas and unconditionally calls the async setter even when nothing changed; upstream filtering removing all entries.","solutions":["Check variables.isEmpty() at the call site and skip the async call when there is nothing to set.","Only call setLocalVariablesAsync when at least one variable must be changed.","If the intent is 'no-op', restructure the caller so the command is never scheduled."],"exampleFix":"// before\ncmmnRuntimeService.setLocalVariablesAsync(planItemId, changedVars); // may be empty\n// after\nif (!changedVars.isEmpty()) {\n    cmmnRuntimeService.setLocalVariablesAsync(planItemId, changedVars);\n}","handlingStrategy":"validation","validationCode":"if (variables == null || variables.isEmpty()) {\n    return; // nothing to set; skip the async command\n}","typeGuard":"boolean isNonEmpty(Map<String, ?> m) { return m != null && !m.isEmpty(); }","tryCatchPattern":"try {\n    cmmnRuntimeService.setLocalVariablesAsync(planItemId, vars);\n} catch (FlowableIllegalArgumentException e) {\n    log.error(\"setLocalVariablesAsync rejected: {}\", e.getMessage());\n}","preventionTips":["Skip the async call when the computed variable delta is empty.","Treat empty-variable operations as no-ops in calling code.","Unit-test batch paths where filters may remove all entries."],"tags":["cmmn","empty-collection","validation"],"backgroundTag":"empty-required-field","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"}