flowable/flowable-engine · error · FlowableIllegalArgumentException

Invalid query usage: cannot set both taskNameIn and…

Error message

Invalid query usage: cannot set both taskNameIn and taskNameLike

What it means

HistoricTaskInstanceQueryImpl.taskNameIn(Collection) throws FlowableIllegalArgumentException when taskNameLike was already set on the same query. An exact-match IN list and a LIKE pattern filter on task name are mutually exclusive in Flowable's query model, so setting both is rejected as invalid query usage. Apply only one task-name filter per query.

Solutions

  1. Set only one name filter: drop taskNameLike when taskNameIn is used (or vice versa).
  2. Implement the 'either' logic explicitly: if a name list is present use taskNameIn, else if a pattern is present use taskNameLike.
  3. Clear/reset the query object between filter assignments, or build a fresh query per request.

Example fix

// before
query.taskNameLike("rev%");
query.taskNameIn(Arrays.asList("review")); // conflict
// after
if (names != null && !names.isEmpty()) {
    query.taskNameIn(names);
} else if (pattern != null) {
    query.taskNameLike(pattern);
}
Defensive patterns

Strategy: validation

Validate before calling

if (pattern != null && names != null && !names.isEmpty()) {
    throw new IllegalStateException("Use either taskNameLike or taskNameIn, not both");
}

Type guard

boolean nameFiltersCompatible(String taskName, String taskNameLike, Collection<String> taskNameIn) {
    int set = (taskName != null ? 1 : 0) + (taskNameLike != null ? 1 : 0) + (taskNameIn != null && !taskNameIn.isEmpty() ? 1 : 0);
    return set <= 1;
}

Try / catch

try {
    query.taskNameIn(names);
} catch (FlowableIllegalArgumentException e) {
    logger.warn("Conflicting task name filters: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling historicTaskInstanceQuery().taskNameLike("rev%").taskNameIn(List.of("review")) — invoking taskNameIn after taskNameLike on the same query object, often through shared builder paths.

Common situations: Search UIs offering both 'name is one of' and 'name contains' filters where both options were submitted; generic query-assembly code that unconditionally sets a LIKE pattern plus an ID-list filter; conditional logic with a missing else branch.

Related errors


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

Appendix: source

Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java:749

            this.taskName = taskName;
        }
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery taskNameIn(Collection<String> taskNameList) {
        if (taskNameList == null) {
            throw new FlowableIllegalArgumentException("Task name list is null");
        }
        if (taskNameList.isEmpty()) {
            throw new FlowableIllegalArgumentException("Task name list is empty");
        }

        if (taskName != null) {
            throw new FlowableIllegalArgumentException("Invalid query usage: cannot set both taskNameIn and taskName");
        }
        if (taskNameLike != null) {
            throw new FlowableIllegalArgumentException("Invalid query usage: cannot set both taskNameIn and taskNameLike");
        }
        if (taskNameLikeIgnoreCase != null) {
            throw new FlowableIllegalArgumentException("Invalid query usage: cannot set both taskNameIn and taskNameLikeIgnoreCase");
        }

        if (inOrStatement) {
            currentOrQueryObject.taskNameList = taskNameList;
        } else {
            this.taskNameList = taskNameList;
        }
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery taskNameInIgnoreCase(Collection<String> taskNameList) {
        if (taskNameList == null) {
            throw new FlowableIllegalArgumentException("Task name list is null");
        }

View on GitHub (pinned to d6d39ce1c6)