{"record":{"id":"52658cae787c0e61","repo":"flowable/flowable-engine","slug":"can-only-enable-a-plan-item-instance-which-is-in-s-52658c","errorCode":null,"errorMessage":"Can only enable a plan item instance which is in state ENABLED","messagePattern":"Can only enable a plan item instance which is in state ENABLED","errorType":"validation","errorClass":"FlowableIllegalStateException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/StartPlanItemInstanceCmd.java","lineNumber":55,"sourceCode":"    }\n\n    public StartPlanItemInstanceCmd(String planItemInstanceId, Map<String, Object> variables,\n            Map<String, Object> formVariables, String formOutcome, FormInfo formInfo,\n            Map<String, Object> localVariables,\n            Map<String, Object> transientVariables, Map<String, Object> childTaskVariables,\n            Map<String, Object> childTaskFormVariables, String childTaskFormOutcome, FormInfo childTaskFormInfo) {\n        \n        super(planItemInstanceId, variables, formVariables, formOutcome, formInfo, localVariables, transientVariables);\n        this.childTaskVariables = childTaskVariables;\n        this.childTaskFormVariables = childTaskFormVariables;\n        this.childTaskFormOutcome = childTaskFormOutcome;\n        this.childTaskFormInfo = childTaskFormInfo;\n    }\n\n    @Override\n    protected void internalExecute(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {\n        if (!PlanItemInstanceState.ENABLED.equals(planItemInstanceEntity.getState())) {\n            throw new FlowableIllegalStateException(\"Can only enable a plan item instance which is in state ENABLED\");\n        }\n        CommandContextUtil.getAgenda(commandContext).planStartPlanItemInstanceOperation(planItemInstanceEntity, null,\n                new ChildTaskActivityBehavior.VariableInfo(childTaskVariables, childTaskFormVariables, childTaskFormOutcome, childTaskFormInfo));\n    }\n    \n}\n","sourceCodeStart":37,"sourceCodeEnd":62,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/StartPlanItemInstanceCmd.java#L37-L62","documentation":"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.).","triggerScenarios":"Calling planItemInstance_START (runtimeService.startPlanItemInstance(planItemInstanceId)) on an instance whose state is not ENABLED — e.g., it already started, was disabled, or completed.","commonSituations":"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.","solutions":["Query the plan item instance state first and only call startPlanItemInstance when state equals ENABLED.","Use the correct operation for the state: triggerPlanItemInstance for AVAILABLE, enable/disable for state transitions.","Handle FlowableIllegalStateException in the UI/API layer and refresh the user's plan item list.","Serialize start requests (optimistic locking / idempotency key) to avoid double-start races."],"exampleFix":"// before\nruntimeService.startPlanItemInstance(planItemInstanceId);\n// after\nPlanItemInstance pii = runtimeService.createPlanItemInstanceQuery()\n    .planItemInstanceId(planItemInstanceId).singleResult();\nif (pii != null && PlanItemInstanceState.ENABLED.equals(pii.getState())) {\n    runtimeService.startPlanItemInstance(planItemInstanceId);\n}","handlingStrategy":"validation","validationCode":"PlanItemInstance pii = runtimeService.createPlanItemInstanceQuery()\n    .planItemInstanceId(id).singleResult();\nboolean startable = pii != null && \"enabled\".equals(pii.getState());","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.startPlanItemInstance(id);\n} catch (FlowableIllegalStateException e) {\n    if (e.getMessage().contains(\"state ENABLED\")) {\n        // refresh UI state; instance already started or unavailable\n    }\n}","preventionTips":["Re-query plan item state before manual start operations","Make start actions idempotent in UIs (disable button after click)","Map state machine operations correctly: start for ENABLED, trigger for AVAILABLE"],"tags":["cmmn","plan-item","invalid-state","concurrency"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}