flowable/flowable-engine · error · ActivitiIllegalArgumentException
Only string values can be used with 'not equals ignore…
Error message
Only string values can be used with 'not equals ignore case' condition
What it means
ActivitiIllegalArgumentException thrown by addVariable when a NOT_EQUALS_IGNORE_CASE condition receives a non-String value. Case-insensitive inequality is only meaningful for strings because the value is lowercased before comparison; other types (or null, rejected earlier) fail fast at build time.
Solutions
- Cast/convert the value to String via String.valueOf(value) before calling.
- Use variableValueNotEquals for non-string types.
- Add a type check at the query-builder boundary that dispatches string values to ignore-case methods and others to plain equals.
Example fix
// before
query.processVariableValueNotEqualsIgnoreCase("category", categoryEnum);
// after
query.processVariableValueNotEqualsIgnoreCase("category", categoryEnum.name()); Defensive patterns
Strategy: type-guard
Validate before calling
if (value instanceof String) {
query.processVariableValueNotEqualsIgnoreCase(name, (String) value);
} else if (value != null) {
query.processVariableValueNotEquals(name, value);
} Type guard
boolean isString(Object o) { return o instanceof String; } Try / catch
try {
query.processVariableValueNotEqualsIgnoreCase(name, value);
} catch (ActivitiIllegalArgumentException e) {
log.warn("Ignore-case exclusion requires a String: {}", e.getMessage());
} Prevention
- Use enums' .name() instead of the enum object when filtering case-insensitively
- Route non-string values to variableValueNotEquals
- Type-check dynamic exclusion filters before applying them
When it happens
Trigger: Calling variableValueNotEqualsIgnoreCase(name, nonStringValue), e.g. with an Integer, Date, or boolean, or via a generic dynamic query layer passing Object values.
Common situations: Exclusion filters built from untyped JSON/config input land in the ignore-case method; refactors that switched from equals to equalsIgnoreCase without changing value types.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Only string values can be used with 'equals ignore case'…
- Only string values can be used with 'like' condition
- activity tenant id is null
- Booleans and null cannot be used in 'greater than' condition
- Booleans and null cannot be used in 'greater than or equal'…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/c775d260d3bbb054.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/AbstractVariableQueryImpl.java:192
if (value == null || isBoolean(value)) {
// Null-values and booleans can only be used in EQUALS and NOT_EQUALS
switch (operator) {
case GREATER_THAN:
throw new ActivitiIllegalArgumentException("Booleans and null cannot be used in 'greater than' condition");
case LESS_THAN:
throw new ActivitiIllegalArgumentException("Booleans and null cannot be used in 'less than' condition");
case GREATER_THAN_OR_EQUAL:
throw new ActivitiIllegalArgumentException("Booleans and null cannot be used in 'greater than or equal' condition");
case LESS_THAN_OR_EQUAL:
throw new ActivitiIllegalArgumentException("Booleans and null cannot be used in 'less than or equal' condition");
}
if (operator == QueryOperator.EQUALS_IGNORE_CASE && !(value instanceof String)) {
throw new ActivitiIllegalArgumentException("Only string values can be used with 'equals ignore case' condition");
}
if (operator == QueryOperator.NOT_EQUALS_IGNORE_CASE && !(value instanceof String)) {
throw new ActivitiIllegalArgumentException("Only string values can be used with 'not equals ignore case' condition");
}
if ((operator == QueryOperator.LIKE || operator == QueryOperator.LIKE_IGNORE_CASE) && !(value instanceof String)) {
throw new ActivitiIllegalArgumentException("Only string values can be used with 'like' condition");
}
}
queryVariableValues.add(new QueryVariableValue(name, value, operator, localScope));
}
private boolean isBoolean(Object value) {
if (value == null) {
return false;
}
return Boolean.class.isAssignableFrom(value.getClass()) || boolean.class.isAssignableFrom(value.getClass());
}
protected void ensureVariablesInitialized() {
if (!queryVariableValues.isEmpty()) {View on GitHub (pinned to d6d39ce1c6)