flowable/flowable-engine · error · FlowableIllegalArgumentException

Variable operation is missing for variable

Error message

Variable operation is missing for variable: ${name}

What it means

FlowableIllegalArgumentException thrown when a variable supplied in an execution/process-instance query has no variableOperation. Each query variable must declare how it should be matched (equals, notEquals, like, etc.); the operation field is mandatory.

Solutions

  1. Add the operation field to each variable in the query body, e.g. "operation":"equals".
  2. If a default-equals was intended, explicitly set operation to equals — there is no implicit default.
  3. Validate the client-side model maps its operation enum to the Flowable QueryVariableOperation names.
  4. Catch FlowableIllegalArgumentException (HTTP 400) and surface a schema error to the caller.

Example fix

// before
{"variables":[{"name":"orderId","value":"42"}]}
// after
{"variables":[{"name":"orderId","value":"42","operation":"equals"}]}
Defensive patterns

Strategy: validation

Validate before calling

for (const v of query.variables) {
  if (!v.operation) throw new Error(`Variable operation missing for ${v.name}`);
}

Type guard

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

Try / catch

try { /* query process instances */ } catch (e) {
  if (e.status === 400 && /Variable operation is missing/.test(e.message)) {
    // fix payload: add operation field
  } else throw e;
}

Prevention

When it happens

Trigger: POST /query/process-instances or /query/executions with body variables:[{"name":"orderId","value":"42"}] omitting the 'operation' field.

Common situations: Hand-written query JSON copied from a non-Flowable example; client library serializes an enum to null; API version change where the field was renamed; user assumes operation defaults to equals.

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

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ExecutionBaseResource.java:128

        if (queryRequest.getTenantIdLike() != null) {
            query.executionTenantIdLike(queryRequest.getTenantIdLike());
        }

        if (Boolean.TRUE.equals(queryRequest.getWithoutTenantId())) {
            query.executionWithoutTenantId();
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessExecutionInfoWithQuery(query, queryRequest);
        }

        return paginateList(requestParams, queryRequest, query, "processInstanceId", allowedSortProperties, restResponseFactory::createExecutionResponseList);
    }

    protected void addVariables(ExecutionQuery processInstanceQuery, List<QueryVariable> variables, boolean process) {
        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 && variable.getVariableOperation() != QueryVariableOperation.EQUALS) {
                throw new FlowableIllegalArgumentException("Value-only query (without a variable-name) is only supported when using 'equals' operation.");
            }

            switch (variable.getVariableOperation()) {

            case EQUALS:
                if (nameLess) {

View on GitHub (pinned to d6d39ce1c6)