flowable/flowable-engine · error · org.flowable.common.engine.api.FlowableIllegalArgumentException

Cannot use taskIds together with excludeLocalVariables

Error message

Cannot use taskIds together with excludeLocalVariables

What it means

Flowable throws this when HistoricVariableInstanceQuery.taskIds(Collection) is called after excludeLocalVariables() has been set. Task-scoped taskIds queries and the excludeLocalVariables filter are semantically incompatible, so the library rejects the combination eagerly at call time instead of producing a misleading query result. This is an argument-consistency guard in HistoricVariableInstanceQueryImpl.taskIds().

Source

Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/HistoricVariableInstanceQueryImpl.java:157

            throw new FlowableIllegalArgumentException("Cannot use taskId together with excludeLocalVariables");
        }
        this.taskId = taskId;
        return this;
    }

    @Override
    public HistoricVariableInstanceQueryImpl taskIds(Set<String> taskIds) {
        if (taskIds == null) {
            throw new FlowableIllegalArgumentException("taskIds is null");
        }
        if (taskIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("Set of taskIds is empty");
        }
        if (excludeTaskRelated) {
            throw new FlowableIllegalArgumentException("Cannot use taskIds together with excludeTaskVariables");
        }
        if (excludeLocalVariables) {
            throw new FlowableIllegalArgumentException("Cannot use taskIds together with excludeLocalVariables");
        }
        this.taskIds = taskIds;
        return this;
    }

    @Override
    public HistoricVariableInstanceQuery excludeTaskVariables() {
        if (taskId != null) {
            throw new FlowableIllegalArgumentException("Cannot use taskId together with excludeTaskVariables");
        }
        if (taskIds != null) {
            throw new FlowableIllegalArgumentException("Cannot use taskIds together with excludeTaskVariables");
        }
        excludeTaskRelated = true;
        return this;
    }

    @Override

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Remove the excludeLocalVariables() call from the query when filtering by taskIds.
  2. Reorder the chain is not enough — the check fires on state, so actually drop one of the two conflicting settings.
  3. If non-local variables are needed per task set, query without excludeLocalVariables and filter results in application code.
  4. Check for conditionally-set flags (e.g. booleans from request parameters) that enable excludeLocalVariables unintentionally.

Example fix

// before
historyService.createHistoricVariableInstanceQuery()
    .taskIds(taskIds)
    .excludeLocalVariables()
    .list();

// after
historyService.createHistoricVariableInstanceQuery()
    .taskIds(taskIds)
    .list();
Defensive patterns

Strategy: validation

Validate before calling

if (excludeLocalVariablesRequested) {
    throw new IllegalStateException("taskIds() cannot be combined with excludeLocalVariables()");
}
// otherwise build the query
query.taskIds(taskIds);

Prevention

When it happens

Trigger: Calling setTaskIds(taskIds) (taskIds setter, line ~157) while the excludeLocalVariables flag is already true — i.e. excludeLocalVariables() was invoked earlier in the fluent chain, or was called before taskIds() in a different order.

Common situations: Building a fluent query where both filters are applied conditionally: a developer wants 'all non-local variables for these tasks' and chains .excludeLocalVariables().taskIds(ids). Also happens when refactoring code from taskId-based to taskIds-based queries without removing the exclusion flag.

Related errors


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