flowable/flowable-engine · error · FlowableIllegalArgumentException
Unsupported variable query operation: " +…
Error message
Unsupported variable query operation: " + variable.getVariableOperation()
What it means
addVariables throws this FlowableIllegalArgumentException when the request's variable query filter specifies a variableOperation value that does not match any supported enum case (EQUALS, NOT_EQUALS, EQUALS_IGNORE_CASE, LIKE, GREATER_THAN, etc.). The default branch of the switch is the guard against unknown/misspelled operations.
Solutions
- Use an exact, supported operation name: EQUALS, NOT_EQUALS, EQUALS_IGNORE_CASE, NOT_EQUALS_IGNORE_CASE, LIKE, LIKE_IGNORE_CASE, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, EXISTS, NOT_EXISTS
- Check the VariableQueryOperation enum in your Flowable version and align the client
- Log the failing request body to identify the malformed operation value
Example fix
// before
{"name":"status","operation":"contains","value":"run"}
// after
{"name":"status","operation":"like","value":"%run%"} Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['EQUALS','NOT_EQUALS','EQUALS_IGNORE_CASE','NOT_EQUALS_IGNORE_CASE','LIKE','LIKE_IGNORE_CASE','GREATER_THAN','GREATER_THAN_OR_EQUAL','LESS_THAN','LESS_THAN_OR_EQUAL','EXISTS','NOT_EXISTS']; if (!ALLOWED.includes(operation)) throw new Error('Unsupported variableOperation: ' + operation); Type guard
function isValidOperation(op, allowed) { return allowed.includes(op); } Try / catch
try { await query(body); } catch (e) { if (e.message.startsWith('Unsupported variable query operation')) { console.error('Bad operation:', body.variable.variableOperation); } } Prevention
- Copy operation names exactly from the VariableQueryOperation enum in your Flowable version
- Pin the Flowable version and regenerate clients after upgrades
- Use an enum type in your client code instead of free-form strings
When it happens
Trigger: Sending a variableQuery with an operation string that is not part of the VariableQueryOperation enum, e.g. "equal", "contains", "", or a typo like "euals"; calling the endpoint after a Flowable upgrade that renamed an operation.
Common situations: Hand-written query strings with wrong casing ("equalsignorecase"); client code built against a different Flowable version; generic UIs letting users type arbitrary operation names.
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
- Unsupported variable query operation
- Only string variable values are supported for like, but…
- Only string variable values are supported using like, but…
- Only string variable values are supported when ignoring…
- Only string variable values are supported when ignoring…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/ee290230e0f6956d.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/BaseProcessInstanceResource.java:369
case LESS_THAN:
processInstanceQuery.variableValueLessThan(variable.getName(), actualValue);
break;
case LESS_THAN_OR_EQUALS:
processInstanceQuery.variableValueLessThanOrEqual(variable.getName(), actualValue);
break;
case EXISTS:
processInstanceQuery.variableExists(variable.getName());
break;
case NOT_EXISTS:
processInstanceQuery.variableNotExists(variable.getName());
break;
default:
throw new FlowableIllegalArgumentException("Unsupported variable query operation: " + variable.getVariableOperation());
}
}
}
/**
* Returns the {@link ProcessInstance} that is requested and calls the access interceptor.
* Throws the right exceptions when bad request was made or instance was not found.
*/
protected ProcessInstance getProcessInstanceFromRequest(String processInstanceId) {
ProcessInstance processInstance = getProcessInstanceFromRequestWithoutAccessCheck(processInstanceId);
if (restApiInterceptor != null) {
restApiInterceptor.accessProcessInstanceInfoById(processInstance);
}
return processInstance;
}
View on GitHub (pinned to d6d39ce1c6)