flowable/flowable-engine · error · FlowableObjectNotFoundException

No case instance found for id ${caseInstanceEntityId}

Error message

No case instance found for id ${caseInstanceEntityId}

What it means

TerminateCaseInstanceOperation.getCaseInstanceEntity lazily loads the case instance row via the CaseInstanceEntityManager. If no row exists for the stored id, the operation cannot proceed and throws FlowableObjectNotFoundException.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/agenda/operation/TerminateCaseInstanceOperation.java:151

        return "cmmn-state-transition-terminate-case";
    }

    @Override
    public void addAdditionalCallbackData(CallbackData callbackData) {
        if (callbackData.getAdditionalData() == null) {
            callbackData.setAdditionalData(new HashMap<>());
        }
        callbackData.getAdditionalData().put(CallbackConstants.EXIT_TYPE, exitType);
        callbackData.getAdditionalData().put(CallbackConstants.EXIT_EVENT_TYPE, exitEventType);
        callbackData.getAdditionalData().put(CallbackConstants.MANUAL_TERMINATION, manualTermination);
    }

    @Override
    public CaseInstanceEntity getCaseInstanceEntity() {
        if (caseInstanceEntity == null) {
            caseInstanceEntity = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(caseInstanceEntityId);
            if (caseInstanceEntity == null) {
                throw new FlowableObjectNotFoundException("No case instance found for id " + caseInstanceEntityId);
            }
        }
        return caseInstanceEntity;
    }

    public boolean isManualTermination() {
        return manualTermination;
    }

    public void setManualTermination(boolean manualTermination) {
        this.manualTermination = manualTermination;
    }

    public String getExitCriterionId() {
        return exitCriterionId;
    }

    public void setExitCriterionId(String exitCriterionId) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the case instance id with CmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(id).count() before terminating.
  2. Treat the termination as already done if the instance no longer exists; catch FlowableObjectNotFoundException as a no-op.
  3. Check for concurrent terminate calls and serialize them.
  4. Ensure you are not passing a historic case instance id to a runtime API.

Example fix

// before
cmmnRuntimeService.terminateCaseInstance(caseInstanceId);
// after
if (cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstanceId).count() > 0) {
    cmmnRuntimeService.terminateCaseInstance(caseInstanceId);
}
Defensive patterns

Strategy: validation

Validate before calling

// java
long exists = cmmnRuntimeService.createCaseInstanceQuery()
    .caseInstanceId(caseInstanceId).count();
if (exists == 0) return; // already gone; skip terminate

Try / catch

try {
    cmmnRuntimeService.terminateCaseInstance(caseInstanceId);
} catch (FlowableObjectNotFoundException e) {
    // instance already terminated/removed: treat as success
}

Prevention

When it happens

Trigger: Agenda operation created/referenced with a caseInstanceEntityId that no longer exists in ACT_CMMN_RU_CASE_INST — e.g. the case was already terminated/removed, or a wrong id was used to construct the operation/trigger the terminate command.

Common situations: Double termination racing so the second one finds no row; terminating with a stale case instance id from history (historic id reuse); database cleanup deleted runtime data.

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/323d78a1fc19c72a. Report an issue: GitHub.