flowable/flowable-engine · error · FlowableIllegalStateException

Can only trigger a plan item that is in the ACTIVE state

Error message

Can only trigger a plan item that is in the ACTIVE state

What it means

CaseTaskActivityBehavior.trigger is invoked when the case task plan item is completed (e.g. the child case finishes or the task is completed programmatically). It requires the plan item instance to still be in the ACTIVE state before completing it; otherwise this error is thrown to protect the lifecycle.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/CaseTaskActivityBehavior.java:166

        planItemInstanceEntity.setReferenceType(ReferenceTypes.PLAN_ITEM_CHILD_CASE);
        planItemInstanceEntity.setReferenceId(caseInstanceEntity.getId());

        if (variablesFromFormSubmission != null && !variablesFromFormSubmission.isEmpty()) {
            // The variablesFromFormSubmission can only be non null if there was formInfo
            cmmnEngineConfiguration.getFormFieldHandler()
                    .handleFormFieldsOnSubmit(variableInfo.formInfo, null, null, caseInstanceEntity.getId(), ScopeTypes.CMMN,
                            variablesFromFormSubmission, caseInstanceEntity.getTenantId());
        }

        if (!blocking) {
            CommandContextUtil.getAgenda(commandContext).planCompletePlanItemInstanceOperation(planItemInstanceEntity);
        }
    }

    @Override
    public void trigger(CommandContext commandContext, PlanItemInstanceEntity planItemInstance) {
        if (!PlanItemInstanceState.ACTIVE.equals(planItemInstance.getState())) {
            throw new FlowableIllegalStateException("Can only trigger a plan item that is in the ACTIVE state");
        }
        if (planItemInstance.getReferenceId() == null) {
            throw new FlowableIllegalStateException("Cannot trigger case task plan item instance : no reference id set");
        }
        if (!ReferenceTypes.PLAN_ITEM_CHILD_CASE.equals(planItemInstance.getReferenceType())) {
            throw new FlowableIllegalStateException("Cannot trigger case task plan item instance : reference type '"
                    + planItemInstance.getReferenceType() + "' not supported");
        }

        // load the case instance referenced by this case task plan item to check its current state
        CaseInstanceEntity caseInstance = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(planItemInstance.getReferenceId());

        if (caseInstance != null) {
            // Out parameters are handled here only when the case is still active (manual trigger scenario).
            // When the child case completed normally, out parameters are already handled
            // in ChildCaseInstanceStateChangeCallback before the child case gets deleted.
            handleOutParameters(commandContext, planItemInstance);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Check planItemInstance state == ACTIVE before triggering/completing the case task.
  2. Ensure exit criteria on the stage do not both terminate the plan item and complete it.
  3. Avoid double-completion: rely on the child case completion to complete the plan item, or guard programmatic triggers.
  4. Fetch a fresh plan item instance state right before triggering to avoid stale-state races.

Example fix

// before
runtimeService.triggerPlanItemInstance(caseTaskPii.getId()); // may double-complete
// after
PlanItemInstance pii = runtimeService.createPlanItemInstanceQuery()
    .planItemInstanceId(caseTaskPii.getId()).singleResult();
if (PlanItemInstanceState.ACTIVE.equals(pii.getState())) {
    runtimeService.triggerPlanItemInstance(pii.getId());
}
Defensive patterns

Strategy: validation

Validate before calling

PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(id).singleResult();
boolean canComplete = pii != null && PlanItemInstanceState.ACTIVE.equals(pii.getState());

Try / catch

try {
    cmmnRuntimeService.triggerPlanItemInstance(id);
} catch (FlowableIllegalStateException e) {
    // plan item not ACTIVE — likely already completed/terminated; ignore if idempotent
}

Prevention

When it happens

Trigger: Completing/triggering a case task plan item instance whose state is not ACTIVE — e.g. the plan item was already terminated, completed by the child case exit, or completed twice concurrently.

Common situations: Child case exit criteria terminating the case task while another thread completes it; calling triggerPlanItemInstance on a case task after the child case already ended; race between exit sentry and completion.

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/45ff84b05dfdfea8. Report an issue: GitHub.