flowable/flowable-engine · error · FlowableIllegalArgumentException
Cannot find process definition with id " +…
Error message
Cannot find process definition with id " + (builder.hasNewProcessDefinitionId() ? builder.getNewProcessDefinitionId() : builder.getProcessDefinitionId())
What it means
ModifyProcessInstanceStartEventSubscriptionCmd.execute() resolves the (possibly latest) process definition for a start event subscription change. When the definition lookup returns null — neither the new process definition id nor the original one can be found — it throws FlowableIllegalArgumentException 'Cannot find process definition with id <id>'.
Solutions
- Verify the process definition id via repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult() before calling.
- Use the definition key and let Flowable resolve the latest version instead of a hard-coded version-specific id.
- If passing a newProcessDefinitionId, confirm it exists and is deployed for the same tenant.
- Catch FlowableIllegalArgumentException and fall back to the current latest definition.
Example fix
// before
migrationBuilder.modifyStartEventSubscription()
.migrateToProcessDefinition(unknownDefId);
// after
ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(unknownDefId).singleResult();
if (def == null) {
def = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(key).latestVersion().singleResult();
}
migrationBuilder.modifyStartEventSubscription().migrateToProcessDefinition(def.getId()); Defensive patterns
Strategy: validation
Validate before calling
ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(targetDefId).singleResult();
if (def == null) {
throw new IllegalArgumentException("Unknown process definition id: " + targetDefId);
} Type guard
boolean definitionExists(String defId) {
return defId != null && repositoryService.createProcessDefinitionQuery()
.processDefinitionId(defId).count() > 0;
} Try / catch
try {
builder.migrateToProcessDefinition(defId);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot find process definition")) {
log.warn("Definition {} not found; using latest by key instead", defId);
}
throw e;
} Prevention
- Resolve definitions by key+latestVersion instead of hard-coded version ids
- Re-resolve ids after redeployments or deployment cleanup
- Check tenant alignment when definitions live in a multi-tenant engine
When it happens
Trigger: Using the process instance migration/modification start-event subscription builder (e.g. migrationBuilder.modifyStartEventSubscription...) with a processDefinitionId that does not exist, was deleted, or refers to another engine's data.
Common situations: Stale ids after redeployment and cleanup of old process definitions; typo in definition id; pointing at a definition deployed to a different tenant/engine; referencing definitions removed by history/deployment cleanup jobs.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Cannot find process definition for id
- Cannot find process definition for key
- Cannot find process definition with id
- Cannot find process definition with id
- Cannot find process definition with id
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/3b5c6c3af985a4eb.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ModifyProcessInstanceStartEventSubscriptionCmd.java:58
protected final ProcessInstanceStartEventSubscriptionModificationBuilderImpl builder;
public ModifyProcessInstanceStartEventSubscriptionCmd(ProcessInstanceStartEventSubscriptionModificationBuilderImpl builder) {
this.builder = builder;
}
@Override
public Void execute(CommandContext commandContext) {
ProcessDefinition newProcessDefinition;
if (builder.hasNewProcessDefinitionId()) {
newProcessDefinition = getProcessDefinitionById(builder.getNewProcessDefinitionId(), commandContext);
} else {
// no explicit process definition provided, so use latest one
ProcessDefinition processDefinition = getProcessDefinitionById(builder.getProcessDefinitionId(), commandContext);
newProcessDefinition = getLatestProcessDefinitionByKey(processDefinition.getKey(), processDefinition.getTenantId(), commandContext);
}
if (newProcessDefinition == null) {
throw new FlowableIllegalArgumentException("Cannot find process definition with id " + (builder.hasNewProcessDefinitionId() ?
builder.getNewProcessDefinitionId() :
builder.getProcessDefinitionId()));
}
Process process = getProcess(newProcessDefinition.getId(), commandContext);
List<StartEvent> startEvents = process.findFlowElementsOfType(StartEvent.class, false);
for (StartEvent startEvent : startEvents) {
// looking for a start event based on an event-registry event subscription
EventRegistryEventDefinition eventDefinition = EventRegistryEventDefinitionUtil.findOn(startEvent);
if (eventDefinition != null && StringUtils.isNotEmpty(eventDefinition.getEventDefinitionKey())) {
// looking for a dynamic, manually subscribed behavior of the event-registry start event
List<ExtensionElement> correlationConfiguration = startEvent.getExtensionElements().get(BpmnXMLConstants.START_EVENT_CORRELATION_CONFIGURATION);
if (correlationConfiguration != null && correlationConfiguration.size() > 0 &&
BpmnXMLConstants.START_EVENT_CORRELATION_MANUAL.equals(correlationConfiguration.get(0).getElementText())) {
String eventDefinitionKey = eventDefinition.getEventDefinitionKey();
String correlationKey = null;View on GitHub (pinned to d6d39ce1c6)