{"record":{"id":"1702fcaf36389230","repo":"flowable/flowable-engine","slug":"a-dynamically-created-plan-item-can-only-be-inject-1702fc","errorCode":null,"errorMessage":"A dynamically created plan item can only be injected into a running stage plan item.","messagePattern":"A dynamically created plan item can only be injected into a running stage plan item\\.","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CreateInjectedPlanItemInstanceCmd.java","lineNumber":110,"sourceCode":"        // after adding the plan item to the stage, add it to the agenda for creation and afterwards for activation processing\n        CmmnEngineAgenda agenda = CommandContextUtil.getAgenda(commandContext);\n        agenda.planCreatePlanItemInstanceOperation(planItemInstanceEntity);\n        agenda.planEvaluateToActivatePlanItemInstanceOperation(planItemInstanceEntity);\n\n        return planItemInstanceEntity;\n    }\n\n    protected PlanItemInstanceEntity getStageInstanceEntity(CommandContext commandContext) {\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        PlanItemInstanceEntity planItemInstanceEntity = cmmnEngineConfiguration.getPlanItemInstanceEntityManager()\n            .findById(planItemInstanceBuilder.getStagePlanItemInstanceId());\n\n        if (planItemInstanceEntity == null) {\n            throw new FlowableIllegalArgumentException(\n                \"The stage plan item instance id \" + planItemInstanceBuilder.getStagePlanItemInstanceId() + \" could not be found or is no longer active.\");\n        }\n        if (!planItemInstanceEntity.isStage()) {\n            throw new FlowableIllegalArgumentException(\"A dynamically created plan item can only be injected into a running stage plan item.\");\n        }\n        return planItemInstanceEntity;\n    }\n\n    protected CaseInstanceEntity getCaseInstanceEntity(CommandContext commandContext) {\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        CaseInstanceEntity caseInstanceEntity = cmmnEngineConfiguration.getCaseInstanceEntityManager().findById(planItemInstanceBuilder.getCaseInstanceId());\n        if (caseInstanceEntity == null) {\n            throw new FlowableIllegalArgumentException(\n                \"The case instance with id \" + planItemInstanceBuilder.getCaseInstanceId() + \" could not be found or is no longer an active case instance.\");\n        }\n        return caseInstanceEntity;\n    }\n}\n","sourceCodeStart":92,"sourceCodeEnd":125,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CreateInjectedPlanItemInstanceCmd.java#L92-L125","documentation":"After finding the plan item instance, CreateInjectedPlanItemInstanceCmd validates that it actually is a stage (PlanItemInstanceEntity.isStage()). Dynamically injected plan items can only be parented under a running stage; injecting into a task or milestone plan item instance is rejected with this FlowableIllegalArgumentException.","triggerScenarios":"Calling the injected plan item builder with stagePlanItemInstanceId set to the id of a non-stage plan item instance (task, user event listener, milestone, or case-level plan item) instead of a stage.","commonSituations":"Selecting an id from a plan item query without filtering on element type; assuming the root/case plan item can host injected items; misreading a child task id as its parent stage id.","solutions":["Query plan item instances filtered to stages, e.g. planItemInstanceQuery.planItemInstanceDefinitionType(\"stage\"), and use that id","Verify the resolved plan item's isStage()/definition type before injecting","If the target should be the case itself, check whether the API requires a case-level injection variant instead of stage injection"],"exampleFix":"// before\nbuilder.stagePlanItemInstanceId(anyPlanItem.getId()).inject();\n// after\nif (anyPlanItem.getPlanItemDefinitionType().equals(\"stage\")) {\n    builder.stagePlanItemInstanceId(anyPlanItem.getId()).inject();\n}","handlingStrategy":"validation","validationCode":"PlanItemInstance pi = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(id).singleResult();\nif (pi == null || !\"stage\".equals(pi.getPlanItemDefinitionType())) throw new IllegalArgumentException(\"target must be a stage\");","typeGuard":"boolean isStage(PlanItemInstance pi) { return pi != null && \"stage\".equals(pi.getPlanItemDefinitionType()); }","tryCatchPattern":"try { builder.stagePlanItemInstanceId(id).inject(); }\ncatch (FlowableIllegalArgumentException e) { if (e.getMessage().contains(\"only be injected into a running stage\")) { /* pick a stage id instead */ } else throw e; }","preventionTips":["Query with planItemInstanceDefinitionType(\"stage\") to select only stages","Do not assume case-level plan items are stages","Unit-test injection code with a real stage id"],"tags":["cmmn","plan-item","invalid-argument-value","stage"],"backgroundTag":"invalid-argument-value","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"}