flowable/flowable-engine · error · FlowableObjectNotFoundException

Form model for case definition

Error message

Form model for case definition ${caseDefinitionId} cannot be found

What it means

GetStartFormModelCmd throws FlowableObjectNotFoundException when the resolved FormInfo is null after querying the form repository. Per the source comment this is deliberate: it avoids leaking which form/definition exists to unauthorized callers.

Solutions

  1. Deploy the form definition referenced by the case model's start form key in the same app/deployment
  2. Confirm the formKey in the Case element matches the deployed form's key and tenant
  3. Check tenantId/parentDeploymentId handling — enable fallbackToDefaultTenant if forms live in the default tenant
  4. Verify the caller is authorized (the null result intentionally hides existence from unauthorized users)

Example fix

// before
FormInfo info = cmmnRuntimeService.getStartFormModel(caseDefId, caseInstanceId); // throws if form missing
// after
FormInfo info = cmmnRuntimeService.getStartFormModel(caseDefId, caseInstanceId);
if (info == null) { /* unreachable: API throws */ }
// deployment side: ensure myStartForm.form is part of the same deployment archive as the case model
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the start form is deployed for this case definition's key/tenant
FormDefinition f = formRepositoryService.createFormDefinitionQuery()
    .latestVersion()
    .formKey(expectedFormKey)
    .tenantId(tenantId).singleResult();

Try / catch

try {
    FormInfo info = cmmnRuntimeService.getStartFormModel(caseDefId, caseInstanceId);
} catch (FlowableObjectNotFoundException e) {
    // treat as 404: form not deployed or user not authorized; do not distinguish
}

Prevention

When it happens

Trigger: Calling getStartFormModel for a case definition whose start form key cannot be found (form not deployed, wrong form key in the model, form deployed under a different parent deployment/tenant), or the authenticated user is not authorized for the form instance scope.

Common situations: Redeploying a case model without its associated .form files; formKey in the CMMN XML not matching the deployed form's key; multi-tenant deployment where the form lives in another tenant; querying with a caseInstanceId whose scope has no form instance yet.

Related errors


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

Appendix: source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/GetStartFormModelCmd.java:72

        if (formService == null) {
            throw new FlowableIllegalArgumentException("Form engine is not initialized");
        }

        FormInfo formInfo = null;
        CaseDefinition caseDefinition = CaseDefinitionUtil.getCaseDefinition(caseDefinitionId);
        CmmnModel cmmnModel = CaseDefinitionUtil.getCmmnModel(caseDefinitionId);
        Case caseModel = cmmnModel.getCaseById(caseDefinition.getKey());
        Stage planModel = caseModel.getPlanModel();

        if (StringUtils.isNotEmpty(planModel.getFormKey())) {
            CmmnDeployment deployment = CommandContextUtil.getCmmnDeploymentEntityManager(commandContext).findById(caseDefinition.getDeploymentId());
            formInfo = formService.getFormInstanceModelByKeyAndParentDeploymentIdAndScopeId(planModel.getFormKey(), deployment.getParentDeploymentId(), 
                            caseInstanceId, ScopeTypes.CMMN, null, caseDefinition.getTenantId(), cmmnEngineConfiguration.isFallbackToDefaultTenant());
        }

        // If form does not exists, we don't want to leak out this info to just anyone
        if (formInfo == null) {
            throw new FlowableObjectNotFoundException("Form model for case definition " + caseDefinitionId + " cannot be found");
        }

        FormFieldHandler formFieldHandler = cmmnEngineConfiguration.getFormFieldHandler();
        formFieldHandler.enrichFormFields(formInfo);

        return formInfo;
    }
}

View on GitHub (pinned to d6d39ce1c6)