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
- Pass the actual process definition id (obtain via repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).latestVersion().singleResult().getId()).
- Check the lookup that produced the id — guard against a null singleResult().
- 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
- Resolve definition ids via createProcessDefinitionQuery at call time.
- Do not hardcode definition ids across environments.
- Distinguish definition key vs id in naming.
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.