{"record":{"id":"02f5844ee6ce038f","repo":"flowable/flowable-engine","slug":"a-dynamically-created-plan-item-can-only-be-inject","errorCode":null,"errorMessage":"A dynamically created plan item can only be injected into a running stage instance or case instance.","messagePattern":"A dynamically created plan item can only be injected into a running stage instance or case instance\\.","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":76,"sourceCode":"        }\n\n        String runningCaseDefinitionId;\n        String caseInstanceId;\n        String tenantId;\n\n        PlanItemInstance stagePlanItemInstance = null;\n        if (planItemInstanceBuilder.injectInStage()) {\n            stagePlanItemInstance = getStageInstanceEntity(commandContext);\n            caseInstanceId = stagePlanItemInstance.getCaseInstanceId();\n            tenantId = stagePlanItemInstance.getTenantId();\n            runningCaseDefinitionId = stagePlanItemInstance.getCaseDefinitionId();\n        } else if (planItemInstanceBuilder.injectInCase()) {\n            CaseInstance caseInstance = getCaseInstanceEntity(commandContext);\n            caseInstanceId = caseInstance.getId();\n            tenantId = caseInstance.getTenantId();\n            runningCaseDefinitionId = caseInstance.getCaseDefinitionId();\n        } else {\n            throw new FlowableIllegalArgumentException(\"A dynamically created plan item can only be injected into a running stage instance or case instance.\");\n        }\n\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        PlanItemInstanceEntity planItemInstanceEntity = cmmnEngineConfiguration.getPlanItemInstanceEntityManager()\n            .createPlanItemInstanceEntityBuilder()\n            .caseDefinitionId(runningCaseDefinitionId)\n            .derivedCaseDefinitionId(planItemInstanceBuilder.getCaseDefinitionId())\n            .planItem((PlanItem) caseElement)\n            .name(planItemInstanceBuilder.getName())\n            .caseInstanceId(caseInstanceId)\n            .stagePlanItemInstance(stagePlanItemInstance)\n            .tenantId(tenantId)\n            .addToParent(true)\n            .create();\n\n        // 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);","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CreateInjectedPlanItemInstanceCmd.java#L58-L94","documentation":"Thrown when the PlanItemInstanceBuilder specifies neither a running stage instance nor a case instance to inject into (injectInCase() is false but no stage instance was set). Dynamic plan items must be attached to an active stage or case instance so the engine knows the parent scope and case definition; neither being set is an invalid builder configuration.","triggerScenarios":"Building a dynamic plan item via planItemInstanceBuilder without calling injectInCase() and without supplying a stage instance (e.g. stageInstanceId / planItemInstanceBuilder.injectInStage(...)), or supplying ids of instances that are not running.","commonSituations":"Forgetting to set the parent scope when constructing the builder programmatically; copying builder code that uses injectInCase but removing the case instance call; misordering builder calls so scope configuration is skipped.","solutions":["Call planItemInstanceBuilder.injectInCase() with a valid, running case instance id when injecting at case level.","Or set the target stage instance for injection into a running stage; confirm the stage is in active state.","Check builder wiring/order so either a stage instance or injectInCase is always configured before executing the command."],"exampleFix":"// before\nPlanItemInstance p = cmmnRuntimeService.createPlanItemInstanceBuilder()\n    .caseDefinitionId(defId).elementId(elementId).create(); // no parent scope\n// after\nPlanItemInstance p = cmmnRuntimeService.createPlanItemInstanceBuilder()\n    .caseDefinitionId(defId).elementId(elementId)\n    .injectInCase()  // or .injectInStage(stageInstanceId)\n    .caseInstanceId(caseInstanceId)\n    .create();","handlingStrategy":"validation","validationCode":"if (stageInstanceId == null && caseInstanceId == null) {\n    throw new IllegalArgumentException(\"Provide a running stage instance or call injectInCase with a caseInstanceId\");\n}\nPlanItemInstanceEntityBuilder b = cmmnRuntimeService.createPlanItemInstanceBuilder()\n    .caseDefinitionId(defId).elementId(elementId);\nif (stageInstanceId != null) {\n    b.injectInStage(stageInstanceId);\n} else {\n    b.injectInCase().caseInstanceId(caseInstanceId);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set a parent scope (stage instance or injectInCase + case instance id) on the builder.","Verify the target case/stage instance is active before injecting."],"tags":["cmmn","builder-validation","dynamic-plan-item","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}