flowable/flowable-engine · error · FlowableIllegalArgumentException
involvedUser is null
Error message
involvedUser is null
What it means
HistoricCaseInstanceQueryImpl.involvedUser(String) throws FlowableIllegalArgumentException when the userId is null. Involvement filtering requires an actual user id to match identity links; a null userId would make the predicate meaningless, so the library validates eagerly.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java:1082
}
@Override
public HistoricCaseInstanceQuery activePlanItemDefinitionIds(Set<String> planItemDefinitionIds) {
if (planItemDefinitionIds == null) {
throw new FlowableIllegalArgumentException("planItemDefinitionIds is null");
}
if (inOrStatement) {
this.currentOrQueryObject.activePlanItemDefinitionIds = planItemDefinitionIds;
} else {
this.activePlanItemDefinitionIds = planItemDefinitionIds;
}
return this;
}
@Override
public HistoricCaseInstanceQuery involvedUser(String userId) {
if (userId == null) {
throw new FlowableIllegalArgumentException("involvedUser is null");
}
if (inOrStatement) {
this.currentOrQueryObject.involvedUser = userId;
} else {
this.involvedUser = userId;
}
return this;
}
@Override
public HistoricCaseInstanceQuery involvedUser(String userId, String identityLinkType) {
if (userId == null) {
throw new FlowableIllegalArgumentException("userId is null");
}
if (identityLinkType == null) {
throw new FlowableIllegalArgumentException("identityLinkType is null");
}
if (inOrStatement) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Check the userId for null/blank before adding the involvement filter.
- Resolve the current user properly and handle the unauthenticated case before building the query.
- If involvement is optional, conditionally add the filter only when a user id exists.
- Validate upstream REST/REST-call inputs so null never reaches the query builder.
Example fix
// before
query.involvedUser(userId); // userId may be null
// after
if (userId != null && !userId.isEmpty()) {
query.involvedUser(userId);
} Defensive patterns
Strategy: validation
Validate before calling
if (userId == null || userId.isEmpty()) {
throw new IllegalArgumentException("userId is required");
}
query.involvedUser(userId); Type guard
boolean hasText(String s) {
return s != null && !s.trim().isEmpty();
} Try / catch
try {
query.involvedUser(userId);
} catch (FlowableIllegalArgumentException e) {
if ("involvedUser is null".equals(e.getMessage())) {
// handle unauthenticated/anonymous case
} else {
throw e;
}
} Prevention
- Resolve and validate the current user before building involvement queries
- Handle anonymous sessions explicitly instead of passing null user ids
- Validate REST parameters for null/blank before query construction
- Centralize user-id resolution in one guarded helper
When it happens
Trigger: Calling involvedUser(null) on a HistoricCaseInstanceQuery, directly or inside an or() block, before executing the query.
Common situations: Current-user resolution (e.g. from SecurityContext/authentication) returned null for anonymous requests; a form or REST parameter was optional and bound to null; user id variable lost during refactoring.
Related errors
- userId is null
- identityLinkType is null
- groupId is null
- groupIds are null
- variableNames is null or empty
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/07792131cba5be48.
Report an issue: GitHub.