{"record":{"id":"90987aded44a523e","repo":"flowable/flowable-engine","slug":"the-case-element-needs-to-be-a-plan-item-but-is-a","errorCode":null,"errorMessage":"The case element needs to be a plan item, but is a ","messagePattern":"The case element needs to be a plan item, but is a ","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":57,"sourceCode":"\n    public CreateInjectedPlanItemInstanceCmd(InjectedPlanItemInstanceBuilderImpl planItemInstanceBuilder) {\n        this.planItemInstanceBuilder = planItemInstanceBuilder;\n    }\n\n    @Override\n    public PlanItemInstance execute(CommandContext commandContext) {\n\n        Case caseModel = CaseDefinitionUtil.getCase(planItemInstanceBuilder.getCaseDefinitionId());\n        if (caseModel == null) {\n            throw new FlowableIllegalArgumentException(\"Could not find case model with case definition id \" + planItemInstanceBuilder.getCaseDefinitionId());\n        }\n\n        CaseElement caseElement = caseModel.getAllCaseElements().get(planItemInstanceBuilder.getElementId());\n        if (caseElement == null) {\n            throw new FlowableIllegalArgumentException(\"Could not find case element with id \" + planItemInstanceBuilder.getElementId());\n        }\n        if (!(caseElement instanceof PlanItem)) {\n            throw new FlowableIllegalArgumentException(\"The case element needs to be a plan item, but is a \" + caseElement.getClass().getName());\n        }\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 {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CreateInjectedPlanItemInstanceCmd.java#L39-L75","documentation":"Thrown when the resolved case element exists but is not a PlanItem instance (e.g. it is a Stage, Milestone, or CasePageTask-level element). Dynamic plan item injection only supports creating new plan items; the elementId must point at a <planItem> in the case model.","triggerScenarios":"Calling planItemInstanceBuilder.elementId(id) where id resolves to a case element that is not a plan item, such as passing a stage id or milestone id from allCaseElements().","commonSituations":"Iterating allCaseElements() and picking the first matching id without checking its type; confusing the plan item's id with the underlying planItemDefinition/task id; passing a milestone id intending to trigger it (which requires a different API).","solutions":["Verify the element is a plan item: if (element instanceof PlanItem) before injecting, otherwise pick the correct planItem id from the model.","Use cmmnModel's getPlanItems()/stage plan items to enumerate only plan item ids.","If you meant to trigger a milestone, use the plan item runtime service triggerPlanItemInstance API instead."],"exampleFix":"// before\nCaseElement el = caseModel.getAllCaseElements().get(elementId);\nplanItemInstanceBuilder.elementId(elementId); // throws if el is a Stage/Milestone\n// after\nCaseElement el = caseModel.getAllCaseElements().get(elementId);\nif (el instanceof PlanItem) {\n    planItemInstanceBuilder.elementId(elementId);\n} else {\n    throw new IllegalStateException(elementId + \" is not a plan item\");\n}","handlingStrategy":"validation","validationCode":"Case caseModel = cmmnRepositoryService.getCmmnModel(caseDefinitionId).getCases().get(0);\nCaseElement el = caseModel.getAllCaseElements().get(elementId);\nif (!(el instanceof PlanItem)) {\n    throw new IllegalArgumentException(\"elementId must reference a planItem, got \" + el.getClass().getSimpleName());\n}\nplanItemInstanceBuilder.elementId(elementId);","typeGuard":"boolean isInjectablePlanItem(CaseElement el) {\n    return el instanceof PlanItem;\n}","tryCatchPattern":null,"preventionTips":["Only enumerate stage.getPlanItems() when choosing dynamic element ids.","Do not pass stage/milestone ids to dynamic plan item builders."],"tags":["cmmn","plan-item","invalid-argument","dynamic-plan-item"],"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-18T11:17:12.947Z"}