flowable/flowable-engine · error · FlowableIllegalArgumentException

privilegeId is null

Error message

privilegeId is null

What it means

GetPrivilegeMappingsByPrivilegeIdCmd's constructor rejects a null privilegeId because privilege mappings are keyed by the privilege's id. The fail-fast FlowableIllegalArgumentException is thrown before the query executes.

Source

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

import org.flowable.common.engine.api.FlowableIllegalArgumentException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.idm.api.PrivilegeMapping;
import org.flowable.idm.engine.impl.util.CommandContextUtil;

/**
 * @author Tijs Rademakers
 */
public class GetPrivilegeMappingsByPrivilegeIdCmd implements Command<List<PrivilegeMapping>>, Serializable {

    private static final long serialVersionUID = 1L;

    protected String privilegeId;

    public GetPrivilegeMappingsByPrivilegeIdCmd(String privilegeId) {
        if (privilegeId == null) {
            throw new FlowableIllegalArgumentException("privilegeId is null");
        }
        this.privilegeId = privilegeId;
    }

    @Override
    public List<PrivilegeMapping> execute(CommandContext commandContext) {
        return CommandContextUtil.getPrivilegeMappingEntityManager(commandContext).getPrivilegeMappingsByPrivilegeId(privilegeId);
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a non-null privilegeId to IdentityService.getPrivilegeMappingsByPrivilegeId().
  2. Resolve the privilege first and handle the not-found case instead of passing a null id.
  3. Validate the request parameter at the controller layer before invoking the engine.
  4. Catch FlowableIllegalArgumentException and return a 'privilegeId required' validation response.

Example fix

// before
List<PrivilegeMapping> mappings = identityService.getPrivilegeMappingsByPrivilegeId(privilegeId); // may be null

// after
Objects.requireNonNull(privilegeId, "privilegeId is required");
List<PrivilegeMapping> mappings = identityService.getPrivilegeMappingsByPrivilegeId(privilegeId);
Defensive patterns

Strategy: validation

Validate before calling

if (privilegeId == null || privilegeId.isEmpty()) {
    throw new IllegalArgumentException("privilegeId must be provided before querying privilege mappings");
}

Type guard

boolean hasValidPrivilegeId(String privilegeId) {
    return privilegeId != null && !privilegeId.isEmpty();
}

Try / catch

try {
    List<PrivilegeMapping> mappings = identityService.getPrivilegeMappingsByPrivilegeId(privilegeId);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("privilegeId is null")) {
        throw new InvalidRequestException("privilegeId must not be null");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling IdentityService.getPrivilegeMappingsByPrivilegeId(null) or constructing new GetPrivilegeMappingsByPrivilegeIdCmd(null), e.g. when listing which users/groups hold a privilege whose id was never resolved.

Common situations: Authorization admin screens where a privilege row's id is null (unsaved privilege); id resolution by name that failed silently; API clients omitting the privilegeId query parameter.

Related errors


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