flowable/flowable-engine · error · FlowableIllegalArgumentException

Candidate user is null

Error message

Candidate user is null

What it means

TaskQueryImpl.taskCandidateUser(String) rejects a null candidate user. The candidate-user filter drives the identity-link join in the query; a null user would produce meaningless SQL, so Flowable validates eagerly and throws FlowableIllegalArgumentException.

Solutions

  1. Resolve the user ID first (e.g. from the security context) and refuse to build the query when it is null.
  2. Skip the candidateUser filter when there is no user, using a different query strategy (e.g. by group or by process).
  3. Fix the authentication/user-resolution code so a real user ID is always available where this query runs.

Example fix

// before
taskQuery.taskCandidateUser(securityService.getCurrentUser());

// after
String userId = securityService.getCurrentUser();
if (userId != null) {
    taskQuery.taskCandidateUser(userId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (candidateUser == null || candidateUser.isEmpty()) { throw new IllegalStateException("candidateUser required for this query"); }
taskQuery.taskCandidateUser(candidateUser);

Type guard

boolean usable = candidateUser != null && !candidateUser.isEmpty();

Try / catch

try {
    taskQuery.taskCandidateUser(userId);
} catch (FlowableIllegalArgumentException e) {
    if (!"Candidate user is null".equals(e.getMessage())) throw e;
    logger.warn("No authenticated user; cannot query candidate tasks");
    return Collections.emptyList();
}

Prevention

When it happens

Trigger: taskQuery.taskCandidateUser(null) — typically when the current user is unknown: no authenticated principal, an unauthenticated request, or a user variable never set.

Common situations: Calling taskService.createTaskQuery().taskCandidateUser(userId) in a scheduled/background job with no user context; a security context returning null user in anonymous flows; upgrading or wiring identity services so userId is no longer populated.

Related errors


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

Appendix: source

Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/TaskQueryImpl.java:578

            if (delegationState == null) {
                currentOrQueryObject.noDelegationState = true;
            } else {
                currentOrQueryObject.delegationState = delegationState;
            }
        } else {
            if (delegationState == null) {
                this.noDelegationState = true;
            } else {
                this.delegationState = delegationState;
            }
        }
        return this;
    }

    @Override
    public TaskQueryImpl taskCandidateUser(String candidateUser) {
        if (candidateUser == null) {
            throw new FlowableIllegalArgumentException("Candidate user is null");
        }

        if (orActive) {
            currentOrQueryObject.candidateUser = candidateUser;
        } else {
            this.candidateUser = candidateUser;
        }

        return this;
    }

    @Override
    public TaskQueryImpl taskInvolvedUser(String involvedUser) {
        if (involvedUser == null) {
            throw new FlowableIllegalArgumentException("Involved user is null");
        }
        if (orActive) {
            currentOrQueryObject.involvedUser = involvedUser;

View on GitHub (pinned to d6d39ce1c6)