flowable/flowable-engine · error · FlowableIllegalArgumentException
user is null
Error message
user is null
What it means
SaveUserCmd persists a User through the UserEntityManager; for new users it also hashes the password with the configured PasswordEncoder and salt. A null User cannot be inserted or updated, so the command throws FlowableIllegalArgumentException immediately.
Source
Thrown at modules/flowable-idm-engine/src/main/java/org/flowable/idm/engine/impl/cmd/SaveUserCmd.java:47
* @author Joram Barrez
*/
public class SaveUserCmd implements Command<Void>, Serializable {
private static final long serialVersionUID = 1L;
protected IdmEngineConfiguration idmEngineConfiguration;
protected User user;
public SaveUserCmd(User user, IdmEngineConfiguration idmEngineConfiguration) {
this.user = user;
this.idmEngineConfiguration = idmEngineConfiguration;
}
@Override
public Void execute(CommandContext commandContext) {
if (user == null) {
throw new FlowableIllegalArgumentException("user is null");
}
if (idmEngineConfiguration.getUserEntityManager().isNewUser(user)) {
if (user.getPassword() != null) {
PasswordEncoder passwordEncoder = idmEngineConfiguration.getPasswordEncoder();
PasswordSalt passwordSalt = idmEngineConfiguration.getPasswordSalt();
user.setPassword(passwordEncoder.encode(user.getPassword(), passwordSalt));
}
if (user instanceof UserEntity) {
idmEngineConfiguration.getUserEntityManager().insert((UserEntity) user, true);
} else {
CommandContextUtil.getDbSqlSession(commandContext).insert((Entity) user, idmEngineConfiguration.getIdGenerator());
}
} else {
UserEntity dbUser = idmEngineConfiguration.getUserEntityManager().findById(user.getId());
user.setPassword(dbUser.getPassword());
idmEngineConfiguration.getUserEntityManager().updateUser(user);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Create the user first (identityService.newUser(id)) and set fields before saving
- Verify the preceding lookup that returned the null user reference
- Null-check before save; create or skip depending on business logic
- Validate request/config payloads so the User object is always populated
Example fix
// before
identityService.saveUser(user);
// after
if (user == null) {
user = identityService.newUser(userId);
user.setPassword(rawPassword);
}
identityService.saveUser(user); Defensive patterns
Strategy: validation
Validate before calling
if (user == null) throw new IllegalArgumentException("user must not be null"); Type guard
boolean isSavableUser(User u) { return u != null && u.getId() != null && !u.getId().trim().isEmpty(); } Try / catch
try { identityService.saveUser(user); } catch (FlowableIllegalArgumentException e) { log.error("Attempted to save null user", e); } Prevention
- Create users via identityService.newUser(id) before saving
- Never pass lookup results to saveUser without a null check
- Validate API/DTO payloads map to a fully populated User
When it happens
Trigger: Calling identityService.saveUser(null) or executing new SaveUserCmd(config, null); also when the user reference comes from a failed lookup or an unbound process/task variable.
Common situations: Chain like saveUser(query().userId(id).singleResult()) when the user no longer exists; user objects built from unvalidated request bodies where the field is absent.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/de5404e13de63b8c.
Report an issue: GitHub.