flowable/flowable-engine · error · FlowableIllegalArgumentException

Unsupported variable query operation

Error message

Unsupported variable query operation: ${operation}

What it means

FlowableIllegalArgumentException thrown when a query variable specifies a variableOperation that is not one of the QueryVariableOperation enum values handled by the switch (equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, like, etc. depending on version). The operation string failed enum parsing into a supported case or fell through to default.

Solutions

  1. Use one of the supported operation names for this endpoint: equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, like (check your Flowable version's QueryVariableOperation).
  2. Upgrade/downgrade the client so its operation vocabulary matches the server's QueryVariableOperation enum.
  3. Log the exact operation string from the request and compare against the enum values in the server version.
  4. Catch FlowableIllegalArgumentException (HTTP 400) and retry with equals.

Example fix

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

Strategy: validation

Validate before calling

const SUPPORTED = ['equals','notEquals','equalsIgnoreCase','notEqualsIgnoreCase','like'];
for (const v of query.variables) {
  if (!SUPPORTED.includes(v.operation)) throw new Error(`Unsupported variable operation: ${v.operation}`);
}

Type guard

const isSupportedOp = (op) => ['equals','notEquals','equalsIgnoreCase','notEqualsIgnoreCase','like'].includes(op);

Try / catch

try { /* query */ } catch (e) {
  if (e.status === 400 && /Unsupported variable query operation/.test(e.message)) {
    // map or degrade the operation to a supported one
  } else throw e;
}

Prevention

When it happens

Trigger: POST /query/process-instances or /query/executions with variables:[{"name":"orderId","value":"42","operation":"greaterThanOrEqual"}] — an operation name that either failed to parse to the enum (then it cannot reach here) or is a valid enum not supported by this switch.

Common situations: Typos in the operation name; copying operation names from other engine versions (Flowable added/removed QueryVariableOperation members across versions); client enumerates operators not supported by this endpoint.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

                    processInstanceQuery.processVariableValueNotEquals(variable.getName(), actualValue);
                } else {
                    processInstanceQuery.variableValueNotEquals(variable.getName(), actualValue);
                }
                break;

            case NOT_EQUALS_IGNORE_CASE:
                if (actualValue instanceof String) {
                    if (process) {
                        processInstanceQuery.processVariableValueNotEqualsIgnoreCase(variable.getName(), (String) actualValue);
                    } else {
                        processInstanceQuery.variableValueNotEqualsIgnoreCase(variable.getName(), (String) actualValue);
                    }
                } else {
                    throw new FlowableIllegalArgumentException("Only string variable values are supported when ignoring casing, but was: " + actualValue.getClass().getName());
                }
                break;
            default:
                throw new FlowableIllegalArgumentException("Unsupported variable query operation: " + variable.getVariableOperation());
            }
        }
    }

    protected Execution getExecutionFromRequest(String executionId) {
        Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
        if (execution == null) {
            throw new FlowableObjectNotFoundException("Could not find an execution with id '" + executionId + "'.", Execution.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessExecutionInfoById(execution);
        }
        
        return execution;
    }

    protected Map<String, Object> getVariablesToSet(List<RestVariable> restVariables) {

View on GitHub (pinned to d6d39ce1c6)