{"record":{"id":"1c7d690f8cdde3db","repo":"flowable/flowable-engine","slug":"no-process-definition-found-for-key-processdefi-1c7d69","errorCode":null,"errorMessage":"No process definition found for key '${processDefinitionKey}'. Fallback to default tenant was also applied.","messagePattern":"No process definition found for key '(.+?)'\\. Fallback to default tenant was also applied\\.","errorType":"exception","errorClass":"FlowableObjectNotFoundException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java","lineNumber":426,"sourceCode":"                }\n            }\n        } else {\n            if (parentDeploymentId != null) {\n                processDefinition = processDefinitionEntityManager\n                        .findProcessDefinitionByParentDeploymentAndKey(parentDeploymentId, processDefinitionKey);\n            }\n            if (processDefinition == null) {\n                processDefinition = processDefinitionEntityManager\n                        .findLatestProcessDefinitionByKey(processDefinitionKey);\n            }\n        }\n\n        if (processDefinition == null) {\n            if (tenantId == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId)) {\n                throw new FlowableObjectNotFoundException(\n                        \"No process definition found for key '\" + processDefinitionKey + \"'\", ProcessDefinition.class);\n            } else if (fallbackToDefaultTenant) {\n                throw new FlowableObjectNotFoundException(\n                        \"No process definition found for key '\" + processDefinitionKey + \"'. Fallback to default tenant was also applied.\", ProcessDefinition.class);\n            } else {\n                throw new FlowableObjectNotFoundException(\n                        \"Process definition with key '\" + processDefinitionKey + \"' and tenantId '\" + tenantId + \"' was not found\", ProcessDefinition.class);\n            }\n        }\n\n        return processDefinition;\n    }\n\n    public void callCaseInstanceStateChangeCallbacks(CommandContext commandContext, ProcessInstance processInstance, String oldState, String newState) {\n        if (processInstance.getCallbackId() != null && processInstance.getCallbackType() != null) {\n            Map<String, List<RuntimeInstanceStateChangeCallback>> caseInstanceCallbacks = CommandContextUtil\n                    .getProcessEngineConfiguration(commandContext).getProcessInstanceStateChangedCallbacks();\n\n            if (caseInstanceCallbacks != null && caseInstanceCallbacks.containsKey(processInstance.getCallbackType())) {\n                for (RuntimeInstanceStateChangeCallback caseInstanceCallback : caseInstanceCallbacks.get(processInstance.getCallbackType())) {\n","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java#L408-L444","documentation":"Thrown by resolveProcessDefinition when a tenantId was supplied, the lookup by key+tenant failed, and a fallback to the default tenant was attempted but also failed to find a definition for that key. Distinguishes the total lookup failure from the simple not-found case.","triggerScenarios":"Starting a process with a tenantId (fallbackToDefaultTenant=true, the default behavior of startProcessInstanceByKey) where neither tenant 'myTenant' nor the default (empty) tenant has any version of the key.","commonSituations":"Multi-tenant deployments where the process was deployed to a different tenant than the one requested; default-tenant deployments removed during cleanup; expecting fallback to find tenant-specific definitions that don't share the key.","solutions":["Deploy the process to the requested tenantId: createDeployment().tenantId(tenant).deploy().","Verify the key spelling against ProcessDefinitionQuery.processDefinitionTenantId(tenant).processDefinitionKey(key).","Check which tenants hold the key: repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list() and use the matching tenant.","If a fallback to the default tenant is intended, deploy a default-tenant (no tenantId) copy of the model."],"exampleFix":"// before\nruntimeService.startProcessInstanceByKey(\"order\", \"tenantB\", vars); // deployed only to tenantA\n// after\nrepositoryService.createDeployment().addClasspathResource(\"order.bpmn20.xml\").tenantId(\"tenantB\").deploy();\nruntimeService.startProcessInstanceByKey(\"order\", \"tenantB\", vars);","handlingStrategy":"validation","validationCode":"List<ProcessDefinition> defs = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list();\nboolean ok = defs.stream().anyMatch(d -> tenantId.equals(d.getTenantId())\n    || ProcessEngineConfiguration.NO_TENANT_ID.equals(d.getTenantId()));\nif (!ok) throw new IllegalStateException(\"Key '\" + key + \"' not deployed for tenant '\" + tenantId + \"' nor default\");","typeGuard":null,"tryCatchPattern":"try {\n    return runtimeService.startProcessInstanceByKey(key, tenantId, vars);\n} catch (FlowableObjectNotFoundException e) {\n    if (e.getMessage().contains(\"Fallback to default tenant\")) {\n        throw new IllegalStateException(\"Deploy for tenant '\" + tenantId + \"' and default tenant first\", e);\n    }\n    throw e;\n}","preventionTips":["Audit tenant deployments with a query on processDefinitionKey across tenants","Standardize tenant ids in configuration, never ad-hoc strings","Remember fallback only reaches the default (empty) tenant","Deploy per-tenant copies in setup scripts"],"tags":["bpmn","tenant","multi-tenancy","not-found","flowable"],"backgroundTag":"resource-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}