flowable/flowable-engine · error · FlowableIllegalStateException

Can only enable a plan item instance which is in state ENABL

Error message

Can only enable a plan item instance which is in state ENABLED

What it means

StartPlanItemInstanceCmd starts a manually-activatable plan item, which is only legal when the plan item instance is currently in ENABLED state (i.e., available for manual start). internalExecute checks the state and throws FlowableIllegalStateException for any other state (ACTIVE, COMPLETED, UNAVAILABLE, DISABLED, etc.).

Source

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

    }

    public StartPlanItemInstanceCmd(String planItemInstanceId, Map<String, Object> variables,
            Map<String, Object> formVariables, String formOutcome, FormInfo formInfo,
            Map<String, Object> localVariables,
            Map<String, Object> transientVariables, Map<String, Object> childTaskVariables,
            Map<String, Object> childTaskFormVariables, String childTaskFormOutcome, FormInfo childTaskFormInfo) {
        
        super(planItemInstanceId, variables, formVariables, formOutcome, formInfo, localVariables, transientVariables);
        this.childTaskVariables = childTaskVariables;
        this.childTaskFormVariables = childTaskFormVariables;
        this.childTaskFormOutcome = childTaskFormOutcome;
        this.childTaskFormInfo = childTaskFormInfo;
    }

    @Override
    protected void internalExecute(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
        if (!PlanItemInstanceState.ENABLED.equals(planItemInstanceEntity.getState())) {
            throw new FlowableIllegalStateException("Can only enable a plan item instance which is in state ENABLED");
        }
        CommandContextUtil.getAgenda(commandContext).planStartPlanItemInstanceOperation(planItemInstanceEntity, null,
                new ChildTaskActivityBehavior.VariableInfo(childTaskVariables, childTaskFormVariables, childTaskFormOutcome, childTaskFormInfo));
    }
    
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Query the plan item instance state first and only call startPlanItemInstance when state equals ENABLED.
  2. Use the correct operation for the state: triggerPlanItemInstance for AVAILABLE, enable/disable for state transitions.
  3. Handle FlowableIllegalStateException in the UI/API layer and refresh the user's plan item list.
  4. Serialize start requests (optimistic locking / idempotency key) to avoid double-start races.

Example fix

// before
runtimeService.startPlanItemInstance(planItemInstanceId);
// after
PlanItemInstance pii = runtimeService.createPlanItemInstanceQuery()
    .planItemInstanceId(planItemInstanceId).singleResult();
if (pii != null && PlanItemInstanceState.ENABLED.equals(pii.getState())) {
    runtimeService.startPlanItemInstance(planItemInstanceId);
}
Defensive patterns

Strategy: validation

Validate before calling

PlanItemInstance pii = runtimeService.createPlanItemInstanceQuery()
    .planItemInstanceId(id).singleResult();
boolean startable = pii != null && "enabled".equals(pii.getState());

Try / catch

try {
    runtimeService.startPlanItemInstance(id);
} catch (FlowableIllegalStateException e) {
    if (e.getMessage().contains("state ENABLED")) {
        // refresh UI state; instance already started or unavailable
    }
}

Prevention

When it happens

Trigger: Calling planItemInstance_START (runtimeService.startPlanItemInstance(planItemInstanceId)) on an instance whose state is not ENABLED — e.g., it already started, was disabled, or completed.

Common situations: Double-click/duplicate submit in a UI starting the same manual task twice; starting from a stale list where state changed; confusion between startPlanItemInstance and enable/disable/trigger operations.

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/52658cae787c0e61. Report an issue: GitHub.