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

  1. Cast/convert the value to String via String.valueOf(value) before calling.
  2. Use variableValueNotEquals for non-string types.
  3. 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

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


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)