{"record":{"id":"30c82659374891f2","repo":"flowable/flowable-engine","slug":"task-taskid-does-not-have-a-variable-varia","errorCode":null,"errorMessage":"Task '${taskId}' does not have a variable '${variableName}' in scope ${scope}","messagePattern":"Task '(.+?)' does not have a variable '(.+?)' in scope (.+?)","errorType":"http","errorClass":"FlowableObjectNotFoundException","httpStatus":404,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/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 = \"/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() + \"' does not 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 executionId, as the hasVariableOnScope would have\n            // stopped a global-var update on standalone task\n            runtimeService.removeVariable(task.getExecutionId(), variableName);\n        }\n    }\n}\n","sourceCodeStart":135,"sourceCodeEnd":169,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskVariableResource.java#L135-L169","documentation":"Deleting a task variable (DELETE /runtime/tasks/{taskId}/variables/{variableName}) first checks that the variable exists in the requested scope (local by default, or global when ?scope=global). If the task does not have that variable in that scope, FlowableObjectNotFoundException is thrown (with VariableInstanceEntity as the missing type), mapping to HTTP 404. It prevents deleting non-existent variables and distinguishes local vs. process-level (global) scopes.","triggerScenarios":"DELETE /runtime/tasks/{taskId}/variables/{variableName}[?scope=local|global] where the variable is not present on the task in the given scope: variable was already deleted, variable exists only at process/execution (global) scope while scope=local is used, name typo, or variable belongs to a different task.","commonSituations":"Variables set at process start are global, but the default scope for this call is local, so deleting them from a task with default scope 404s; double-delete in retry logic; wrong task id; case-sensitive name mismatch.","solutions":["Add ?scope=global when the variable was set at the process/execution level rather than on the task.","GET the task's variables first to confirm the exact name and scope before deleting.","Fix the task id / variable name (names are case-sensitive).","Treat 404 as idempotent success if deletion may have already happened."],"exampleFix":"// before: variable is global (set on process), default local scope fails\ncurl -X DELETE .../runtime/tasks/123/variables/orderStatus\n\n// after\ncurl -X DELETE .../runtime/tasks/123/variables/orderStatus?scope=global","handlingStrategy":"validation","validationCode":"const vars = await fetch(`/runtime/tasks/${taskId}/variables?scope=${scope}`).then(r => r.json());\nif (!vars.some(v => v.name === variableName)) {\n  return; // nothing to delete; skip the DELETE call\n}","typeGuard":null,"tryCatchPattern":"try {\n  const resp = await fetch(url, { method: 'DELETE' });\n  if (resp.status === 404) return; // idempotent: already gone or wrong scope\n  if (!resp.ok) throw new Error(await resp.text());\n} catch (e) {\n  if (!isNotFound(e)) throw e;\n}","preventionTips":["List the task's variables (with scope) before deleting to confirm existence.","Remember process-level variables need ?scope=global; the default scope is local.","Treat 404 as success in cleanup/retry logic to stay idempotent.","Variable names are case-sensitive — verify exact spelling."],"tags":["rest-api","flowable","resource-not-found","variables"],"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-14T05:17:10.506Z"}