flowable/flowable-engine · error · FlowableIllegalArgumentException

Variable operation is missing for variable: ${variable.getNa

Error message

Variable operation is missing for variable: ${variable.getName()}

What it means

FlowableIllegalArgumentException thrown while building a historic task instance query when a supplied query variable has no variableOperation set. The REST variable query parameter requires an explicit operation (equals, greaterThan, exists, etc.); an operation-less variable is an invalid request body. This is a client request validation error (HTTP 400).

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/task/HistoricTaskInstanceBaseResource.java:325

    }

    /**
     * Returns the {@link HistoricTaskInstance} that is requested without calling the access interceptor
     * Throws the right exceptions when bad request was made or instance was not found.
     */
    protected HistoricTaskInstance getHistoricTaskInstanceFromRequestWithoutAccessCheck(String taskId) {
        HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (taskInstance == null) {
            throw new FlowableObjectNotFoundException("Could not find a task instance with id '" + taskId + "'.", HistoricTaskInstance.class);
        }
        
        return taskInstance;
    }

    protected void addTaskVariables(HistoricTaskInstanceQuery taskInstanceQuery, List<QueryVariable> variables) {
        for (QueryVariable variable : variables) {
            if (variable.getVariableOperation() == null) {
                throw new FlowableIllegalArgumentException("Variable operation is missing for variable: " + variable.getName());
            }
            if (variable.getVariableOperation() != QueryVariableOperation.EXISTS && variable.getVariableOperation() != QueryVariableOperation.NOT_EXISTS) {
                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()) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add the required 'operation' field to each variable object in the query body (e.g. "operation":"equals").
  2. Use one of the supported QueryVariableOperation values: EQUALS, NOT_EQUALS, EQUALS_IGNORE_CASE, NOT_EQUALS_IGNORE_CASE, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, LIKE, EXISTS, NOT_EXISTS, etc.
  3. Validate the request payload client-side before sending; reject variables without an operation.
  4. Check client serialization is not omitting the operation due to null/naming mismatch.

Example fix

// before
{"taskVariableValues":[{"name":"priority","value":1}]}
// after
{"taskVariableValues":[{"name":"priority","value":1,"operation":"EQUALS"}]}
Defensive patterns

Strategy: validation

Validate before calling

function validateQueryVars(vars) {
  for (const v of vars.taskVariableValues || []) {
    if (!v.operation) throw new Error("variable '" + v.name + "' is missing 'operation'");
  }
}

Type guard

const hasOperation = (v) => typeof v.operation === 'string' && v.operation.length > 0;

Prevention

When it happens

Trigger: POST /cmmn-history/historic-task-instances/query (variable handling inside getQueryResponse) with a body like {"taskVariableValues":[{"name":"priority"}]} - the variable object omits the 'operation' field.

Common situations: Hand-written JSON query bodies missing the operation key; client DTO serialization dropping the operation field; upgrading clients against older API shapes that defaulted operations.

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/bb0e4a884c799ba0. Report an issue: GitHub.