{"record":{"id":"3c02d731e6a9f5e0","repo":"flowable/flowable-engine","slug":"plan-item-instance-id-does-not-have-a-variabl","errorCode":null,"errorMessage":"Plan item instance '${id}' does not have a variable '${variableName}' in local scope","messagePattern":"Plan item instance '(.+?)' does not have a variable '(.+?)' in local scope","errorType":"http","errorClass":"FlowableObjectNotFoundException","httpStatus":404,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/PlanItemInstanceVariableResource.java","lineNumber":178,"sourceCode":"            setSimpleVariable(restVariable, planItem.getId(), false, true, RestVariable.RestVariableScope.LOCAL, CmmnRestResponseFactory.VARIABLE_PLAN_ITEM, createVariableInterceptor(planItem));\n        }\n    }\n\n    @ApiOperation(value = \"Delete a variable for a plan item instance\", tags = { \"Plan Item Instances\" }, nickname = \"deletePlanItemVariable\", code = 204)\n    @ApiResponses(value = {\n            @ApiResponse(code = 204, message = \"Indicates both the plan item and variable were found and variable has been deleted.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested plan item was not found or the plan item does not have a variable with the given name in the requested scope. Status description contains additional information about the error.\")\n    })\n    @ResponseStatus(HttpStatus.NO_CONTENT)\n    @DeleteMapping(value = \"/cmmn-runtime/plan-item-instances/{planItemInstanceId}/variables/{variableName}\")\n    public void deleteVariable(@ApiParam(name = \"planItemInstanceId\") @PathVariable(\"planItemInstanceId\") String planItemInstanceId,\n            @ApiParam(name = \"variableName\") @PathVariable(\"variableName\") String variableName,\n            @RequestParam(value = \"scope\", required = false) String scope) {\n\n        PlanItemInstance planItem = getPlanItemInstanceFromRequest(planItemInstanceId);\n\n        if (!runtimeService.hasLocalVariable(planItem.getId(), variableName)) {\n            throw new FlowableObjectNotFoundException(\n                    \"Plan item instance '\" + planItem.getId() + \"' does not have a variable '\" + variableName + \"' in local scope\",\n                    VariableInstance.class);\n        }\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.deletePlanItemInstanceVariables(planItem, Collections.singleton(variableName));\n        }\n        runtimeService.removeLocalVariable(planItem.getId(), variableName);\n    }\n}\n","sourceCodeStart":160,"sourceCodeEnd":189,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/PlanItemInstanceVariableResource.java#L160-L189","documentation":"deleteVariable checks runtimeService.hasLocalVariable(planItem.getId(), variableName); when the plan item instance has no such variable in LOCAL scope it throws FlowableObjectNotFoundException with VariableInstance.class. Only local scope is consulted here — an instance-scope (case) variable with the same name will not satisfy this check.","triggerScenarios":"DELETE /cmmn-runtime/plan-item-instances/{planItemInstanceId}/variables/{variableName} where the variable was never set locally, was already deleted, or exists only in case (global) scope.","commonSituations":"Assuming variables set on the case are visible as plan-item-local variables; double DELETE from concurrent workers; variable removed by a completed plan item; wrong planItemInstanceId (typo or from an ended case).","solutions":["Check the variable exists locally via GET .../variables?scope=local before deleting.","If the variable lives in case scope, delete it via the case-instance variable endpoint instead.","Handle 404 idempotently — deleting an already-deleted variable should be treated as success by the caller.","Verify planItemInstanceId is from an active case instance."],"exampleFix":"// before\ndelete(\"/plan-item-instances/\" + id + \"/variables/\" + name); // may 404 if only case-scoped\n// after\nif (get(\"/plan-item-instances/\" + id + \"/variables/\" + name + \"?scope=local\")) {\n  delete(\"/plan-item-instances/\" + id + \"/variables/\" + name);\n}","handlingStrategy":"try-catch","validationCode":"// pre-check local existence\nconst vars = rest.get(`/cmmn-runtime/plan-item-instances/${id}/variables?scope=local`);\nif (!vars.some(v => v.name === variableName)) return; // nothing local to delete","typeGuard":null,"tryCatchPattern":"try { api.deletePlanItemVariable(planItemId, name); }\ncatch (FlowableObjectNotFoundException e) {\n  if (e.getResourceClass() == VariableInstance.class) { log.info('already deleted or case-scoped'); return; }\n  throw e;\n}","preventionTips":["Remember deleteVariable only targets LOCAL scope; case-scoped variables need the case-instance endpoint.","Make deletes idempotent in workers (tolerate 404).","Use optimistic locking or dedup keys to avoid concurrent double-deletes.","Verify the plan item instance is still active before deleting."],"tags":["rest-api","not-found","variables","scope","cmmn"],"backgroundTag":"entity-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}