flowable/flowable-engine · error · FlowableIllegalArgumentException

Variable operation is missing for variable:

Error message

Variable operation is missing for variable: 

What it means

Thrown as FlowableIllegalArgumentException when a variable query predicate supplied to the historic variable instance query has no 'operation' field. The REST query endpoint accepts a variables filter array where each entry needs name, value, and operation (e.g. equals, like, greaterThan); operation is mandatory. Without it the query cannot know which operator to apply, so the request is rejected as invalid (HTTP 400).

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/variable/HistoricVariableInstanceBaseResource.java:119

    }
    
    public RestVariable getVariableFromRequest(boolean includeBinary, String varInstanceId) {
        HistoricVariableInstance varObject = historyService.createHistoricVariableInstanceQuery().id(varInstanceId).singleResult();

        if (varObject == null) {
            throw new FlowableObjectNotFoundException("Historic variable instance '" + varInstanceId + "' couldn't be found.", VariableInstanceEntity.class);
        } else {
            if (restApiInterceptor != null) {
                restApiInterceptor.accessHistoryVariableInfoById(varObject);
            }
            return restResponseFactory.createRestVariable(varObject.getVariableName(), varObject.getValue(), null, varInstanceId, CmmnRestResponseFactory.VARIABLE_HISTORY_VARINSTANCE, includeBinary);
        }
    }

    protected void addVariables(HistoricVariableInstanceQuery variableInstanceQuery, List<QueryVariable> variables) {
        for (QueryVariable variable : variables) {
            if (variable.getVariableOperation() == null) {
                throw new FlowableIllegalArgumentException("Variable operation is missing for variable: " + variable.getName());
            }
            if (variable.getValue() == null) {
                throw new FlowableIllegalArgumentException("Variable value is missing for variable: " + variable.getName());
            }

            boolean nameLess = variable.getName() == null;

            Object actualValue = restResponseFactory.getVariableValue(variable);

            // A value-only query is only possible using equals-operator
            if (nameLess) {
                throw new FlowableIllegalArgumentException("Value-only query (without a variable-name) is not supported");
            }

            switch (variable.getVariableOperation()) {

            case EQUALS:
                variableInstanceQuery.variableValueEquals(variable.getName(), actualValue);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add the required operation to each variable filter, e.g. {"name":"status","value":"done","operation":"equals"}.
  2. Use one of the supported operations: equals, notEquals, greaterThan, greaterThanOrEquals, lessThan, lessThanOrEquals, like, ignoreCaseEquals (per QueryVariable.QueryVariableOperation).
  3. Fix JSON key spelling/casing so the operation field actually binds during deserialization.
  4. Validate the query payload client-side before sending: every variable entry must have non-null name (or intentionally nameless) and operation.

Example fix

// before: 400 - operation missing
{"variables":[{"name":"status","value":"done"}]}

// after
{"variables":[{"name":"status","value":"done","operation":"equals"}]}
Defensive patterns

Strategy: validation

Validate before calling

if (variables.stream().anyMatch(v -> v.getOperation() == null)) {
    throw new IllegalArgumentException("every variable filter needs an operation (equals, like, ...)");
}

Try / catch

try {
    HistoricVariableInstanceListResponse r = query(variables);
} catch (FlowableIllegalArgumentException e) {
    // HTTP 400: invalid variable filter payload
}

Prevention

When it happens

Trigger: POST-style query GET /cmmn-history/historic-variable-instances?variables=... (or query body) with a variable entry like {"name":"status","value":"done"} lacking "operation":"equals", or a client serializing QueryVariable objects with a null variableOperation.

Common situations: Hand-built query strings that omit the operation parameter, older client SDKs whose model predates the operation field, or JSON payloads where the operation key is misspelled (e.g. 'op') so it deserializes to null.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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