{"record":{"id":"392601338875c5cb","repo":"flowable/flowable-engine","slug":"task-taskid-doesn-t-have-a-variable-variab","errorCode":null,"errorMessage":"Task '${taskId}' doesn't have a variable '${variableName}' in scope ${scope}","messagePattern":"Task '(.+?)' doesn't have a variable '(.+?)' in scope (.+?)","errorType":"http","errorClass":"FlowableObjectNotFoundException","httpStatus":404,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskVariableResource.java","lineNumber":153,"sourceCode":"            @ApiResponse(code = 204, message = \"Indicates the task variable was found and has been deleted. Response-body is intentionally empty.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested task was not found or the task does not have a variable with the given name. Status message contains additional information about the error.\")\n    })\n    @DeleteMapping(value = \"/cmmn-runtime/tasks/{taskId}/variables/{variableName}\")\n    @ResponseStatus(HttpStatus.NO_CONTENT)\n    public void deleteVariable(@ApiParam(name = \"taskId\") @PathVariable(\"taskId\") String taskId,\n            @ApiParam(name = \"variableName\") @PathVariable(\"variableName\") String variableName,\n            @ApiParam(hidden = true) @RequestParam(value = \"scope\", required = false) String scopeString) {\n\n        Task task = getTaskFromRequestWithoutAccessCheck(taskId);\n\n        // Determine scope\n        RestVariableScope scope = RestVariableScope.LOCAL;\n        if (scopeString != null) {\n            scope = RestVariable.getScopeFromString(scopeString);\n        }\n\n        if (!hasVariableOnScope(task, variableName, scope)) {\n            throw new FlowableObjectNotFoundException(\"Task '\" + task.getId() + \"' doesn't have a variable '\" + variableName + \"' in scope \" + scope.name().toLowerCase(), VariableInstanceEntity.class);\n        }\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.deleteTaskVariables(task, Collections.singleton(variableName), scope);\n        }\n\n        if (scope == RestVariableScope.LOCAL) {\n            taskService.removeVariableLocal(task.getId(), variableName);\n        } else {\n            // Safe to use scope id, as the hasVariableOnScope would have\n            // stopped a global-var update on standalone task\n            runtimeService.removeVariable(task.getScopeId(), variableName);\n        }\n    }\n}\n","sourceCodeStart":135,"sourceCodeEnd":169,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskVariableResource.java#L135-L169","documentation":"This FlowableObjectNotFoundException is thrown by the CMMN REST API when a DELETE request for a task variable cannot find the named variable on the task in the requested scope (LOCAL by default, or GLOBAL/ANY). The API validates that the variable exists before deleting it, so deleting a non-existent variable fails rather than silently succeeding.","triggerScenarios":"DELETE /cmmn-runtime/tasks/{taskId}/variables/{variableName} (optionally with ?scope=global|local) where the task has no variable with that name in the requested scope. Note default scope is LOCAL, so a global-only variable will also trigger this if scope is not specified.","commonSituations":"Client caches stale variable lists after the variable was already deleted; variable exists only in GLOBAL scope but request omits scope=global; typo in variable name; task already completed and its local variables were removed.","solutions":["Set the correct scope query parameter (e.g. ?scope=global) if the variable lives in the global/case scope","Verify the variable name via GET /cmmn-runtime/tasks/{taskId}/variables before deleting","Check the task is still active; completed/terminated tasks may have purged variables","Handle 404 in the client as an idempotent success if the goal is just to remove the variable"],"exampleFix":"// before\ndelete /cmmn-runtime/tasks/{taskId}/variables/orderId\n// after\ndelete /cmmn-runtime/tasks/{taskId}/variables/orderId?scope=global","handlingStrategy":"try-catch","validationCode":"const vars = await fetch(`/cmmn-runtime/tasks/${taskId}/variables`); const exists = (await vars.json()).some(v => v.name === variableName);","typeGuard":"function hasVariable(vars, name, scope) { return Array.isArray(vars) && vars.some(v => v.name === name && (scope === undefined || v.scope === undefined || v.scope === scope)); }","tryCatchPattern":"try { await deleteVariable(taskId, variableName, scope); } catch (e) { if (e.status === 404 && /doesn't have a variable/.test(e.message)) { /* treat as already deleted */ } else { throw e; } }","preventionTips":["List a task's variables before deleting to confirm name and scope","Always pass the explicit scope when the variable is global","Treat 404 on delete as idempotent success in retry logic"],"tags":["rest-api","variables","not-found"],"backgroundTag":"resource-not-found","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"}