flowable/flowable-engine · error · FlowableIllegalArgumentException

processDefinitionId is null

Error message

processDefinitionId is null

What it means

AddIdentityLinkForProcessDefinitionCmd.validateParams() throws when processDefinitionId is null. Candidate starter links attach to a specific process definition, so its id is a mandatory parameter checked before execution.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/AddIdentityLinkForProcessDefinitionCmd.java:51

    private static final long serialVersionUID = 1L;

    protected String processDefinitionId;

    protected String userId;

    protected String groupId;

    public AddIdentityLinkForProcessDefinitionCmd(String processDefinitionId, String userId, String groupId) {
        validateParams(userId, groupId, processDefinitionId);
        this.processDefinitionId = processDefinitionId;
        this.userId = userId;
        this.groupId = groupId;
    }

    protected void validateParams(String userId, String groupId, String processDefinitionId) {
        if (processDefinitionId == null) {
            throw new FlowableIllegalArgumentException("processDefinitionId is null");
        }

        if (userId == null && groupId == null) {
            throw new FlowableIllegalArgumentException("userId and groupId cannot both be null");
        }
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        ProcessDefinitionEntity processDefinition = processEngineConfiguration.getProcessDefinitionEntityManager().findById(processDefinitionId);

        if (processDefinition == null) {
            throw new FlowableObjectNotFoundException("Cannot find process definition with id " + processDefinitionId, ProcessDefinition.class);
        }

        if (Flowable5Util.isFlowable5ProcessDefinition(processDefinition, commandContext)) {
            Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass the actual process definition id (obtain via repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).latestVersion().singleResult().getId()).
  2. Check the lookup that produced the id — guard against a null singleResult().
  3. Confirm you are not confusing processDefinitionId with processInstanceId or definition key.

Example fix

// before
repositoryService.addCandidateStarterProcessDefinition(defId, "kermit", null); // defId == null
// after
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey("myProcess").latestVersion().singleResult();
if (pd != null) {
    repositoryService.addCandidateStarterProcessDefinition(pd.getId(), "kermit", null);
}
Defensive patterns

Strategy: validation

Validate before calling

if (processDefinitionId == null || processDefinitionId.isEmpty()) {
    throw new IllegalArgumentException("processDefinitionId required");
}

Type guard

boolean hasDefinitionId(ProcessDefinition pd) { return pd != null && pd.getId() != null; }

Try / catch

try {
    repositoryService.addCandidateStarterProcessDefinition(defId, userId, groupId);
} catch (FlowableIllegalArgumentException | FlowableObjectNotFoundException e) {
    log.error("Cannot add candidate starter: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling repositoryService.addCandidateStarterProcessDefinition(null, userId, groupId) or constructing the command with a null definition id, often when the id comes from a failed definition lookup.

Common situations: Using createProcessDefinitionQuery().singleResult() which returned null; passing a processInstanceId instead of processDefinitionId by mistake; wiring the wrong variable in scripts.

Related errors


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