{"record":{"id":"cbc8698a5456f1b4","repo":"flowable/flowable-engine","slug":"could-not-resolve-case-instance-id","errorCode":null,"errorMessage":"Could not resolve case instance id","messagePattern":"Could not resolve case instance id","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/DefaultCmmnDynamicStateManager.java","lineNumber":38,"sourceCode":"import org.flowable.cmmn.model.PlanItemDefinition;\nimport org.flowable.common.engine.api.FlowableException;\nimport org.flowable.common.engine.impl.interceptor.CommandContext;\n\n/**\n * @author Tijs Rademakers\n */\npublic class DefaultCmmnDynamicStateManager extends AbstractCmmnDynamicStateManager implements CmmnDynamicStateManager {\n    \n    public DefaultCmmnDynamicStateManager(CmmnEngineConfiguration cmmnEngineConfiguration) {\n        super(cmmnEngineConfiguration);\n    }\n\n    @Override\n    public void movePlanItemInstanceState(ChangePlanItemStateBuilderImpl changePlanItemStateBuilder, CommandContext commandContext) {\n        String caseInstanceId = changePlanItemStateBuilder.getCaseInstanceId();\n        \n        if (caseInstanceId == null) {\n            throw new FlowableException(\"Could not resolve case instance id\");\n        }\n        \n        CaseInstanceEntityManager caseInstanceEntityManager = CommandContextUtil.getCaseInstanceEntityManager(commandContext);\n        CaseInstanceEntity caseInstance = caseInstanceEntityManager.findById(caseInstanceId);\n        \n        String originalCaseDefinitionId = caseInstance.getCaseDefinitionId();\n        \n        CaseInstanceChangeState caseInstanceChangeState = new CaseInstanceChangeState()\n            .setCaseInstanceId(caseInstanceId)\n            .setActivatePlanItemDefinitions(changePlanItemStateBuilder.getActivatePlanItemDefinitions())\n            .setTerminatePlanItemDefinitions(changePlanItemStateBuilder.getTerminatePlanItemDefinitions())\n            .setChangePlanItemDefinitionsToAvailable(changePlanItemStateBuilder.getChangeToAvailableStatePlanItemDefinitions())\n            .setWaitingForRepetitionPlanItemDefinitions(changePlanItemStateBuilder.getWaitingForRepetitionPlanItemDefinitions())\n            .setRemoveWaitingForRepetitionPlanItemDefinitions(changePlanItemStateBuilder.getRemoveWaitingForRepetitionPlanItemDefinitions())\n            .setCaseVariables(changePlanItemStateBuilder.getCaseVariables())\n            .setChildInstanceTaskVariables(changePlanItemStateBuilder.getChildInstanceTaskVariables());\n        \n        doMovePlanItemState(caseInstanceChangeState, originalCaseDefinitionId, commandContext);","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/DefaultCmmnDynamicStateManager.java#L20-L56","documentation":"DefaultCmmnDynamicStateManager.movePlanItemInstanceState resolves the case instance from the builder's caseInstanceId before performing dynamic plan item state moves. If the builder has no case instance id, the state manager cannot locate the aggregate root to modify, and a FlowableException is thrown.","triggerScenarios":"Building a ChangePlanItemStateBuilder without calling caseInstanceId(...) (or passing null) and then invoking changeState(); using a builder obtained from a service that failed to populate the id.","commonSituations":"Programmatic builder construction missing the id; the case instance id variable null because a previous lookup failed; copying builder setup code and dropping the caseInstanceId call.","solutions":["Set a valid case instance id via changePlanItemStateBuilder.caseInstanceId(id) before changeState()","Load the id from the CaseInstance query and assert it is non-null before building","Check that the API path you use is cmmnRuntimeService.createChangePlanItemStateBuilder(caseInstanceId), which sets the id for you"],"exampleFix":"// before\nruntimeService.createChangePlanItemStateBuilder(null) // or builder without caseInstanceId\n    .movePlanItemInstanceState(\"pi1\", \"active\").changeState();\n// after\nCaseInstance ci = runtimeService.createCaseInstanceQuery().caseInstanceBusinessKey(\"BK-1\").singleResult();\nruntimeService.createChangePlanItemStateBuilder(ci.getId())\n    .movePlanItemInstanceState(\"pi1\", \"active\").changeState();","handlingStrategy":"validation","validationCode":"if (caseInstanceId == null || caseInstanceId.isEmpty()) throw new IllegalArgumentException(\"caseInstanceId required\");","typeGuard":"boolean hasText(String s) { return s != null && !s.trim().isEmpty(); }","tryCatchPattern":"try { builder.changeState(); } catch (FlowableException e) { log.error(\"caseInstanceId missing: {}\", e.getMessage()); }","preventionTips":["Use cmmnRuntimeService.createChangePlanItemStateBuilder(caseInstanceId) which sets the id","Resolve the case instance id from a query and assert non-null before building","Do not propagate nullable ids into builder construction"],"tags":["flowable","cmmn","plan-item","validation","null-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-14T11:17:12.474Z"}