flowable/flowable-engine · error · FlowableIllegalArgumentException

userId is null

Error message

userId is null

What it means

DeleteUserCmd.execute() verifies userId is non-null before calling the UserEntityManager's delete. Deleting a user without an identifier is meaningless, so the engine throws FlowableIllegalArgumentException.

Solutions

  1. Pass a non-null userId to IdentityService.deleteUser().
  2. Confirm the user exists (createUserQuery().userId(id).singleResult()) before deleting.
  3. Filter null ids out of bulk-deletion loops before invoking the engine.
  4. Catch FlowableIllegalArgumentException and convert to a domain validation error.

Example fix

// before
identityService.deleteUser(userId); // userId may be null

// after
Objects.requireNonNull(userId, "userId is required");
identityService.deleteUser(userId);
Defensive patterns

Strategy: validation

Validate before calling

if (userId == null || userId.isEmpty()) {
    throw new IllegalArgumentException("userId must be provided before deleting a user");
}

Type guard

boolean hasValidUserId(String userId) {
    return userId != null && !userId.isEmpty();
}

Try / catch

try {
    identityService.deleteUser(userId);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("userId is null")) {
        throw new InvalidRequestException("User id must not be null");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling IdentityService.deleteUser(null) or executing new DeleteUserCmd(null), e.g. during user-provisioning cleanup where the id came from an unset variable or failed lookup.

Common situations: User-deletion flows triggered by SCIM/LDAP sync events with missing ids; REST DELETE endpoints with a null path variable after framework coercion; scripts deleting test users whose id was renamed.

Related errors


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

Appendix: source

Thrown at modules/flowable-idm-engine/src/main/java/org/flowable/idm/engine/impl/cmd/DeleteUserCmd.java:37

import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.idm.engine.impl.util.CommandContextUtil;

/**
 * @author Tom Baeyens
 */
public class DeleteUserCmd implements Command<Void>, Serializable {

    private static final long serialVersionUID = 1L;
    String userId;

    public DeleteUserCmd(String userId) {
        this.userId = userId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (userId == null) {
            throw new FlowableIllegalArgumentException("userId is null");
        }
        CommandContextUtil.getUserEntityManager(commandContext).delete(userId);

        return null;
    }
}

View on GitHub (pinned to d6d39ce1c6)