flowable/flowable-engine · error · IllegalStateException

Provided process definition must have a deployment id.

Error message

Provided process definition must have a deployment id.

What it means

getPersistedInstanceOfProcessDefinition requires the given process definition entity to already be attached to a deployment, because it looks the definition up by deploymentId + key. If deploymentId is null or empty it fails fast with this IllegalStateException rather than issuing a meaningless query.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/deployer/BpmnDeploymentHelper.java:158

        ProcessDefinitionEntity existingDefinition = null;

        if (tenantId != null && !tenantId.equals(ProcessEngineConfiguration.NO_TENANT_ID)) {
            existingDefinition = processDefinitionManager.findLatestDerivedProcessDefinitionByKeyAndTenantId(key, tenantId);
        } else {
            existingDefinition = processDefinitionManager.findLatestDerivedProcessDefinitionByKey(key);
        }

        return existingDefinition;
    }

    /**
     * Gets the persisted version of the already-deployed process definition. Note that this is different from {@link #getMostRecentVersionOfProcessDefinition} as it looks specifically for a process
     * definition that is already persisted and attached to a particular deployment, rather than the latest version across all deployments.
     */
    public ProcessDefinitionEntity getPersistedInstanceOfProcessDefinition(ProcessDefinitionEntity processDefinition) {
        String deploymentId = processDefinition.getDeploymentId();
        if (StringUtils.isEmpty(processDefinition.getDeploymentId())) {
            throw new IllegalStateException("Provided process definition must have a deployment id.");
        }

        ProcessDefinitionEntityManager processDefinitionManager = CommandContextUtil.getProcessEngineConfiguration().getProcessDefinitionEntityManager();
        ProcessDefinitionEntity persistedProcessDefinition = null;
        if (processDefinition.getTenantId() == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(processDefinition.getTenantId())) {
            persistedProcessDefinition = processDefinitionManager.findProcessDefinitionByDeploymentAndKey(deploymentId, processDefinition.getKey());
        } else {
            persistedProcessDefinition = processDefinitionManager.findProcessDefinitionByDeploymentAndKeyAndTenantId(deploymentId, processDefinition.getKey(), processDefinition.getTenantId());
        }

        return persistedProcessDefinition;
    }

    /**
     * Updates all timers and events for the process definition. The undeploy half iterates the previous
     * process definition's top-level start events; each behavior either does its own per-start-event work
     * (e.g. the EventRegistry "manual" re-point) or registers an obsolete event subscription / timer job
     * handler type with the context. After the undeploy iteration the deployer issues one mass-delete per

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Only call this method after the definition has been persisted and its deploymentId set
  2. If you need the latest definition regardless of deployment, use getMostRecentVersionOfProcessDefinition instead
  3. Persist the deployment (or let the standard Persister/Deployer pipeline run) before invoking this helper
  4. Guard custom code with a null/empty deploymentId check and skip or reroute accordingly

Example fix

// before
helper.getPersistedInstanceOfProcessDefinition(unsavedDefinition);

// after
if (StringUtils.isNotEmpty(unsavedDefinition.getDeploymentId())) {
    helper.getPersistedInstanceOfProcessDefinition(unsavedDefinition);
} else {
    helper.getMostRecentVersionOfProcessDefinition(unsavedDefinition);
}
Defensive patterns

Strategy: validation

Validate before calling

if (processDefinition.getDeploymentId() == null || processDefinition.getDeploymentId().isEmpty()) {
    // use latest-version lookup instead
    return bpmnDeploymentHelper.getMostRecentVersionOfProcessDefinition(processDefinition);
}

Prevention

When it happens

Trigger: Calling BpmnDeploymentHelper.getPersistedInstanceOfProcessDefinition with a ProcessDefinitionEntity that has not yet been persisted/assigned a deploymentId — e.g. during deployment before the entity is saved, or a programmatically built definition.

Common situations: Custom deployers or extension code invoking the helper with an in-memory (unsaved) definition; calling it in the wrong deployment lifecycle phase; mixing up getMostRecentVersionOfProcessDefinition with getPersistedInstanceOfProcessDefinition.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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