flowable/flowable-engine · error · FlowableObjectNotFoundException

Process definition ${processDefinitionKey} was not found in

Error message

Process definition ${processDefinitionKey} was not found in sameDeployment[${isSameDeployment}] tenantId[${tenantId}] fallbackToDefaultTenant[${this.fallbackToDefaultTenant}]

What it means

CallActivityBehavior.getProcessDefinitionByKey resolves the called process by key, honoring sameDeployment, tenantId and fallbackToDefaultTenant. If no matching deployed process definition is found under those constraints, it throws FlowableObjectNotFoundException detailing all the resolution parameters. This is the standard 'called process not deployed (or not visible to this tenant)' error.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CallActivityBehavior.java:329

        if (tenantId == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId)) {
            processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKey(processDefinitionKey);
        } else {
            processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId);
            if (processDefinition == null && ((this.fallbackToDefaultTenant != null && this.fallbackToDefaultTenant) || processEngineConfiguration.isFallbackToDefaultTenant())) {

                String defaultTenant = processEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(tenantId, ScopeTypes.BPMN, processDefinitionKey);
                if (StringUtils.isNotEmpty(defaultTenant)) {
                    processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKeyAndTenantId(
                                    processDefinitionKey, defaultTenant);
                } else {
                    processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKey(processDefinitionKey);
                }
            }
        }

        if (processDefinition == null) {
            throw new FlowableObjectNotFoundException("Process definition " + processDefinitionKey + " was not found in sameDeployment["+ isSameDeployment +
                "] tenantId["+ tenantId+ "] fallbackToDefaultTenant["+ this.fallbackToDefaultTenant + "]");
        }
        return processDefinition;
    }

    protected String getCalledElementValue(DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
        String calledElementValue = callActivity.getCalledElement();
        if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()){
            ObjectNode taskElementProperties = BpmnOverrideContext
                    .getBpmnOverrideElementProperties(callActivity.getId(), execution.getProcessDefinitionId());
            calledElementValue = getActiveValue(callActivity.getCalledElement(), DynamicBpmnConstants.CALL_ACTIVITY_CALLED_ELEMENT, taskElementProperties);
        }
        if (StringUtils.isNotEmpty(calledElementValue) && calledElementValue.matches(EXPRESSION_REGEX)) {
            calledElementValue = (String) processEngineConfiguration.getExpressionManager().createExpression(calledElementValue).getValue(execution);
        }
        return calledElementValue;
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Deploy the process with the missing key (include its BPMN XML in the parent's BAR or deploy it separately for the same tenant).
  2. Set fallbackToDefaultTenant=true on the call activity if a tenantless default deployment of the subprocess should be used.
  3. Check what exists: repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).processDefinitionTenantId(tenantId).list() and align tenantId/sameDeployment.
  4. If versioning independently, set sameDeployment=false so the latest definition by key across deployments is used.
  5. Fix typos in the calledElement key.

Example fix

// before: tenant 'acme' cannot see subprocess deployed without tenant, fallback disabled
<callActivity id="c" calledElement="subProcess" flowable:fallbackToDefaultTenant="false"/>
// after
<callActivity id="c" calledElement="subProcess" flowable:fallbackToDefaultTenant="true"/>
Defensive patterns

Strategy: validation

Validate before calling

ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
    .processDefinitionKey("subProcess")
    .processDefinitionTenantId(tenantId)
    .latestVersion().singleResult();
if (def == null) throw new IllegalStateException("Deploy subprocess for tenant " + tenantId + " before starting parent");

Try / catch

try { startParent(); }
catch (FlowableObjectNotFoundException e) { if (e.getMessage().contains("Process definition")) { deployMissingSubProcess(); } else { throw e; } }

Prevention

When it happens

Trigger: A call activity with calledElementType=key executes and: the key is not deployed at all; sameDeployment=true and the key isn't in the same deployment; the process is deployed under a different tenantId and fallbackToDefaultTenant=false.

Common situations: Sub process forgotten from the deployment BAR file; tenant-aware deployments where the tenant's deployment lacks the subprocess; sameDeployment=true combined with separately versioned subprocess deployments; key typos or renamed process keys.

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


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