flowable/flowable-engine · error · FlowableIllegalArgumentException

Cannot exit case with 'complete' event type as the case '${c

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.

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)

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.