flowable/flowable-engine · error · FlowableIllegalArgumentException
userId is null
Error message
userId is null
What it means
startableByUser(String) restricts a ProcessDefinitionQuery to definitions the given user can start. Flowable throws FlowableIllegalArgumentException when userId is null since start-authorization filtering requires a concrete user identity.
Solutions
- Resolve and pass the actual Flowable user id of the potential starter.
- Skip the startableByUser call (and any authorization filter) for unauthenticated/anonymous listings.
- Fail fast earlier with a clear 'authentication required' error instead of the query-time argument error.
Example fix
// before
String userId = SecurityUtils.getCurrentUserId();
return repositoryService.createProcessDefinitionQuery().startableByUser(userId).list();
// after
String userId = SecurityUtils.getCurrentUserId();
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
if (userId != null) {
query.startableByUser(userId);
}
return query.list(); Defensive patterns
Strategy: validation
Validate before calling
if (userId != null) { query.startableByUser(userId); } Try / catch
try { query.startableByUser(userId); } catch (FlowableIllegalArgumentException e) { throw new AuthenticationRequiredException("user must be authenticated to filter by starter"); } Prevention
- Require authentication before queries that filter by user.
- Skip authorization filters for anonymous listing endpoints explicitly.
- Keep user-id resolution in one utility that throws a clear auth error on missing identity.
When it happens
Trigger: Calling startableByUser(null), usually when the current authenticated user is not resolved (anonymous session, missing security context) and the user id variable is null.
Common situations: Endpoints exposed without authentication; task/list UIs showing definitions before login; identities stored in an external IdP where the Flowable user id mapping is absent.
Related errors
- activatedBefore is null
- activity tenant id is null
- after time is null
- Assignee is null
- AssigneeLike is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/991b22afb4732102.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/ProcessDefinitionQueryImpl.java:360
this.eventSubscriptionName = eventName;
return this;
}
public Collection<String> getAuthorizationGroups() {
if (authorizationGroupsSet) {
// if authorizationGroupsSet is true then startableByUserOrGroups was called
// and the groups passed in that methods have precedence
return authorizationGroups;
} else if (authorizationUserId == null) {
return null;
}
return CommandContextUtil.getProcessEngineConfiguration().getCandidateManager().getGroupsForCandidateUser(authorizationUserId);
}
@Override
public ProcessDefinitionQueryImpl startableByUser(String userId) {
if (userId == null) {
throw new FlowableIllegalArgumentException("userId is null");
}
this.authorizationUserId = userId;
return this;
}
@Override
public ProcessDefinitionQuery startableByUserOrGroups(String userId, Collection<String> groups) {
if (userId == null && (groups == null || groups.isEmpty())) {
throw new FlowableIllegalArgumentException("userId is null and groups are null or empty");
}
this.authorizationUserId = userId;
this.authorizationGroups = groups;
this.authorizationGroupsSet = true;
return this;
}
// sorting ////////////////////////////////////////////
View on GitHub (pinned to d6d39ce1c6)