flowable/flowable-engine · error · FlowableIllegalArgumentException

caseDefinitionKey and caseDefinitionId are null

Error message

caseDefinitionKey and caseDefinitionId are null

What it means

CaseInstanceHelperImpl.getCaseDefinition resolves a CaseDefinition either by caseDefinitionId or by caseDefinitionKey (via the deployment cache/repository). If the CaseInstanceBuilder supplied neither identifier, the engine cannot locate which case definition to start and throws FlowableIllegalArgumentException. This is a fail-fast guard because starting a case without a definition reference is meaningless.

Solutions

  1. Set caseDefinitionKey (e.g. builder.caseDefinitionKey("myCase")) before calling startCaseInstance.
  2. Alternatively set the exact caseDefinitionId if you resolved the deployed definition already.
  3. Validate the incoming request/dto for a non-null definition key or id before invoking the engine.

Example fix

// before
cmmnRuntimeService.createCaseInstanceBuilder().businessKey("BK-1").start();
// after
cmmnRuntimeService.createCaseInstanceBuilder()
    .caseDefinitionKey("loanApplicationCase")
    .businessKey("BK-1")
    .start();
Defensive patterns

Strategy: validation

Validate before calling

if (caseDefinitionKey == null && caseDefinitionId == null) {
    throw new IllegalArgumentException("Provide caseDefinitionKey or caseDefinitionId before starting a case instance");
}

Try / catch

try {
    runtimeService.createCaseInstanceBuilder().caseDefinitionKey(key).start();
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("caseDefinitionKey and caseDefinitionId are null")) {
        // surface a 400 to the caller indicating the definition reference is required
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling CmmnRuntimeService.startCaseInstance (or the async variant) with a CaseInstanceBuilder where both caseDefinitionId and caseDefinitionKey are null/never set.

Common situations: Building the start request dynamically from user input or a request payload where the definition reference key was omitted; copying builder code that set the id but was refactored; REST/API layer dropping the field when deserializing the start request.

Related errors


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

Appendix: source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelperImpl.java:183

            CmmnDeploymentManager deploymentManager = cmmnEngineConfiguration.getDeploymentManager();
            caseDefinition = deploymentManager.findDeployedCaseDefinitionById(caseDefinitionId);

        } else if (caseInstanceBuilder.getCaseDefinitionKey() != null) {
            String caseDefinitionKey = caseInstanceBuilder.getCaseDefinitionKey();
            String tenantId = caseInstanceBuilder.getTenantId();
            String parentDeploymentId = caseInstanceBuilder.getCaseDefinitionParentDeploymentId();

            caseDefinition = resolveCaseDefinition(caseDefinitionKey, tenantId,
                    caseInstanceBuilder.isFallbackToDefaultTenant() || cmmnEngineConfiguration.isFallbackToDefaultTenant(),
                    parentDeploymentId);

            if (caseDefinition != null && tenantId != null && !CmmnEngineConfiguration.NO_TENANT_ID.equals(tenantId)
                    && !tenantId.equals(caseDefinition.getTenantId())) {
                // Case definition comes from the fallback to the default tenant
                caseInstanceBuilder.overrideCaseDefinitionTenantId(tenantId);
            }
        } else {
            throw new FlowableIllegalArgumentException("caseDefinitionKey and caseDefinitionId are null");
        }
        return caseDefinition;
    }

    protected CaseInstanceEntity startCaseInstance(CommandContext commandContext, CaseDefinition caseDefinition, CaseInstanceBuilder caseInstanceBuilder) {
        CmmnModel cmmnModel = getCmmnModel(commandContext, caseDefinition);
        Case caseModel = getCaseModel(caseDefinition, cmmnModel);
        CaseInstanceEntity caseInstanceEntity = initializeCaseInstanceEntity(commandContext, caseDefinition, 
                cmmnModel, caseModel, caseInstanceBuilder);

        if (!caseModel.isAsync()) {
            // The InitPlanModelOperation will take care of initializing all the child plan items of that stage
            CommandContextUtil.getAgenda(commandContext).planInitPlanModelOperation(caseInstanceEntity);

            CaseInstanceLifeCycleListenerUtil.callLifecycleListeners(commandContext, caseInstanceEntity, "", CaseInstanceState.ACTIVE);

            FlowableEventDispatcher eventDispatcher = cmmnEngineConfiguration.getEventDispatcher();
            if (eventDispatcher != null && eventDispatcher.isEnabled()) {

View on GitHub (pinned to d6d39ce1c6)