{"record":{"id":"a6f7d3dbe73251c1","repo":"apache/pulsar","slug":"delete-request-ignored-because-it-is-out-of-date","errorCode":null,"errorMessage":"Delete request ignored because it is out of date. Please try again.","messagePattern":"Delete request ignored because it is out of date\\. Please try again\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/FunctionMetaDataManager.java","lineNumber":264,"sourceCode":"            throw new IllegalStateException(\"Internal Error updating function at the leader\", e);\n        }\n\n        if (needsScheduling) {\n            this.schedulerManager.schedule();\n        }\n    }\n\n    private void checkRequestOutDated(FunctionMetaData functionMetaData, boolean delete) {\n        FunctionDetails details = functionMetaData.getFunctionDetails();\n        if (isRequestOutdated(details.getTenant(), details.getNamespace(),\n                details.getName(), functionMetaData.getVersion())) {\n            log.debug().attr(\"tenant\", details.getTenant())\n                    .attr(\"namespace\", details.getNamespace())\n                    .attr(\"functionName\", details.getName())\n                    .attr(\"version\", functionMetaData.getVersion())\n                    .log(\"Ignoring outdated request version\");\n            if (delete) {\n                throw new IllegalArgumentException(\n                        \"Delete request ignored because it is out of date. Please try again.\");\n            }\n            throw new IllegalArgumentException(\"Update request ignored because it is out of date. Please try again.\");\n        }\n    }\n\n    /**\n     * Acquires a exclusive producer.  This method cannot return null.  It can only return a valid exclusive producer\n     * or throw NotLeaderAnymore exception.\n     * @param isLeader if the worker is still the leader\n     * @return A valid exclusive producer\n     * @throws WorkerUtils.NotLeaderAnymore if the worker is no longer the leader.\n     */\n    public Producer<byte[]> acquireExclusiveWrite(Supplier<Boolean> isLeader) throws WorkerUtils.NotLeaderAnymore {\n        // creates exclusive producer for metadata topic\n        return WorkerUtils.createExclusiveProducerWithRetry(\n                pulsarClient,\n                workerConfig.getFunctionMetadataTopic(),","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/FunctionMetaDataManager.java#L246-L282","documentation":"checkRequestOutDated compares the incoming delete request's metadata version against the locally cached function metadata. If the request's version is older or equal to the current version (isRequestOutdated true), the delete is stale and the manager throws IllegalArgumentException(\"Delete request ignored because it is out of date. Please try again.\") to force the client to re-read and resubmit.","triggerScenarios":"Calling updateFunctionOnLeader(..., delete=true) (via deregisterFunction) with a FunctionMetaData whose version does not advance beyond the version currently stored in the worker's functionMetaData cache — typically a replayed or delayed delete request.","commonSituations":"Client retried an old delete after a previous one already succeeded; admin client read metadata from a lagging worker/replica; two admins issued conflicting deletes and the loser's version is stale.","solutions":["Re-read the current function metadata (GET function) and retry the delete with a version greater than the cached version.","Treat this as a benign retry signal, not a hard failure — the function may already be deleted.","Verify the delete actually succeeded before retrying to avoid pointless loops.","Avoid long-lived stale FunctionMetaData objects; fetch fresh metadata immediately before each delete."],"exampleFix":"// before\nworker.deregisterFunction(tenant, namespace, functionName, staleMeta);\n// after\nFunctionMetaData current = getFunctionMetaData(tenant, namespace, functionName);\nif (current != null) {\n    FunctionMetaData fresh = current.toBuilder().setVersion(current.getVersion() + 1).build();\n    worker.deregisterFunction(tenant, namespace, functionName, fresh);\n}","handlingStrategy":"retry","validationCode":"FunctionMetaData current = admin.functions().getFunctionMetaData(tenant, ns, fn);\nif (deleteMeta.getVersion() <= current.getVersion()) {\n    throw new IllegalArgumentException(\"Delete request is stale; refetch before deleting\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    worker.deregisterFunction(tenant, ns, fn, meta);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Delete request ignored\")) {\n        // function likely already deleted or version stale — refetch and retry once\n    } else {\n        throw e;\n    }\n}","preventionTips":["Fetch fresh metadata immediately before every delete.","Check whether the function still exists before retrying a delete.","Avoid reusing cached FunctionMetaData objects across operations."],"tags":["pulsar-functions","version-conflict","optimistic-concurrency"],"backgroundTag":"stale-request-version","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}