flowable/flowable-engine · error · FlowableIllegalArgumentException

Cannot exit case with 'complete' event type as the case

Error message

Cannot exit case with 'complete' event type as the case '${caseInstanceId}' is not yet completable. The plan item '${planItemName} (${planItemDefinitionId})' prevented it from completion.

What it means

TerminateCaseInstanceOperation.checkCaseToBeCompletable, invoked during preRunCheck, evaluates whether the case's plan model can complete. When a case is exited with event type 'complete' but a child plan item still prevents completion, the engine refuses with a FlowableIllegalArgumentException naming the blocking plan item.

Solutions

  1. Complete the blocking plan item (shown in the message) before terminating.
  2. Use the plain exit/terminate event type instead of 'complete' when unconditional termination is desired.
  3. Adjust sentry/criteria so case completion is achievable at the point of exit.
  4. Intercept the FlowableIllegalArgumentException in the terminate API call and report the blocking item to the user.

Example fix

// before: <criterion sentryRef="killSentry"> with sentry onEvent="complete"
// after: unconditional exit
<sentry id="killSentry">
  <planItemOnPart sourceRef="killSignal"/>
</sentry>
Defensive patterns

Strategy: try-catch

Validate before calling

// java: check blocking active children before 'complete' exit of case
List<PlanItemInstance> active = cmmnRuntimeService.createPlanItemInstanceQuery()
    .caseInstanceId(caseInstanceId).planItemInstanceState("active").list();
if (!active.isEmpty()) throw new IllegalStateException("Case has active plan items; complete-exit will fail");

Try / catch

try {
    cmmnRuntimeService.terminateCaseInstance(caseInstanceId);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("is not yet completable")) {
        // prompt user to finish blocking plan item
    }
}

Prevention

When it happens

Trigger: Manually terminating a case with the 'complete' exit semantics (or an event fires it) while active children (tasks, listeners) still block case completion; isAutoComplete evaluation fails in shouldPlanItemContainerComplete.

Common situations: Administrator terminate actions against cases with unfinished human tasks; exit criteria with 'complete' event type misused where plain 'exit' was intended; incomplete milestones.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

        }
    }

    /**
     * Checks, if the case is completable and if not, raises an exception.
     */
    protected void checkCaseToBeCompletable() {
        CaseInstanceEntity caseInstance = getCaseInstanceEntity();
        boolean isAutoComplete = getPlanModel(caseInstance).isAutoComplete();

        // if the case should exit with a complete event instead of exit, we need to make sure it is completable
        // we don't use the completion flag directly on the entity as it gets evaluated only at the end of an evaluation cycle which we didn't hit yet
        // at this point, so we need a proper evaluation of the completion
        CompletionEvaluationResult completionEvaluationResult = PlanItemInstanceContainerUtil
            .shouldPlanItemContainerComplete(commandContext, caseInstance, isAutoComplete);

        if (!completionEvaluationResult.isCompletable()) {
            // we can't complete the case as it is currently not completable, so we need to throw an exception
            throw new FlowableIllegalArgumentException(
                "Cannot exit case with 'complete' event type as the case '" + getCaseInstanceId() + "' is not yet completable. The plan item '" +
                    completionEvaluationResult.getPlanItemInstance().getName() + " (" +
                    completionEvaluationResult.getPlanItemInstance().getPlanItemDefinitionId() + ")' prevented it from completion.");
        }
    }

    @Override
    public String getNewState() {
        // depending on the exit event type, we will end up in the complete state, even though the case was actually terminated / exited
        if (EXIT_EVENT_TYPE_COMPLETE.equals(exitEventType) || EXIT_EVENT_TYPE_FORCE_COMPLETE.equals(exitEventType)) {
            return CaseInstanceState.COMPLETED;
        }
        return CaseInstanceState.TERMINATED;
    }
    
    @Override
    public void changeStateForChildPlanItemInstance(PlanItemInstanceEntity planItemInstanceEntity) {
        // if the plan item implements the specific behavior interface for ending, invoke it, otherwise use the default one which is terminate, regardless,

View on GitHub (pinned to d6d39ce1c6)