{"record":{"id":"4209e9f8a43f5075","repo":"apache/pulsar","slug":"failed-to-delete-cookie-for-bookie-bookieid","errorCode":null,"errorMessage":"Failed to delete cookie for bookie ${bookieId}","messagePattern":"Failed to delete cookie for bookie (.+?)","errorType":"exception","errorClass":"BookieException.MetadataStoreException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java","lineNumber":286,"sourceCode":"        } catch (ExecutionException | TimeoutException e) {\n            throw new BookieException.MetadataStoreException(e);\n        }\n    }\n\n    @Override\n    public void removeCookie(BookieId bookieId, Version version) throws BookieException {\n        String path = this.cookiePath + \"/\" + bookieId;\n        try {\n            store.delete(path, Optional.of(((LongVersion) version).getLongVersion()))\n                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw new BookieException.MetadataStoreException(\"Interrupted deleting cookie for bookie \" + bookieId, e);\n        } catch (ExecutionException e) {\n            if (e.getCause() instanceof MetadataStoreException.NotFoundException) {\n                throw new BookieException.CookieNotFoundException(bookieId.toString());\n            } else {\n                throw new BookieException.MetadataStoreException(\"Failed to delete cookie for bookie \" + bookieId);\n            }\n        } catch (TimeoutException ex) {\n            throw new BookieException.MetadataStoreException(\"Failed to delete cookie for bookie \" + bookieId);\n        }\n\n        log.info().attr(\"cookiePath\", cookiePath).attr(\"bookieId\", bookieId).log(\"Removed cookie for bookie\");\n    }\n\n    @Override\n    public boolean prepareFormat() throws Exception {\n        boolean ledgerRootExists = store.exists(ledgersRootPath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        boolean availableNodeExists = store.exists(bookieRegistrationPath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        // Create ledgers root node if not exists\n        if (!ledgerRootExists) {\n            store.put(ledgersRootPath, new byte[0], Optional.empty())\n                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        }\n        // create available bookies node if not exists","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java#L268-L304","documentation":"PulsarRegistrationManager.removeCookie() deletes a bookie's cookie from the metadata store. When the underlying async delete fails with an ExecutionException whose cause is NOT a NotFoundException (i.e., not a missing cookie, which gets its own CookieNotFoundException), the manager wraps it in BookieException.MetadataStoreException with this message. The original cause is dropped, so only the bookie id is reported.","triggerScenarios":"Calling removeCookie when the metadata store delete fails with a BadVersionException (version conflict passed as `version`), a store connection loss, a session expiry, or any metadata-store error other than NotFound.","commonSituations":"Decommissioning a bookie whose cookie was concurrently modified/deleted by another process; metadata store outage or network partition; wrong expected version supplied (stale Version object).","solutions":["Check metadata store connectivity/health (ZooKeeper/Oxia) before retrying removeCookie","If the cause is a version conflict, re-fetch the cookie to obtain a fresh Version and retry, or pass Optional.empty()/new LongVersion(-1) semantics if unconditional delete is intended","Verify the bookie id and cookie path are correct and no concurrent decommission is running","Inspect server-side metadata store logs for the underlying delete error, since the message omits the cause"],"exampleFix":"// before\nregistrationManager.removeCookie(bookieId, staleVersion);\n// after\nVersioned<byte[]> cookie = registrationManager.readBookieCookie(bookieId);\nregistrationManager.removeCookie(bookieId, cookie.getVersion());","handlingStrategy":"try-catch","validationCode":"// Java\nMetadataStore store = ...;\nif (!store.exists(cookiePath + \"/\" + bookieId).get(30, TimeUnit.SECONDS)) {\n    // cookie absent -> removeCookie is unnecessary\n}\n","typeGuard":"boolean cookieExists(MetadataStore store, BookieId id) {\n    try {\n        return store.exists(\"/cookies/\" + id).get(30, TimeUnit.SECONDS);\n    } catch (Exception e) { return false; }\n}\n","tryCatchPattern":"try {\n    registrationManager.removeCookie(bookieId, version);\n} catch (BookieException.CookieNotFoundException e) {\n    // already gone: idempotent success\n} catch (BookieException.MetadataStoreException e) {\n    // check store health, re-read cookie for fresh Version, retry\n}\n","preventionTips":["Re-read the cookie to obtain a fresh Version immediately before removeCookie","Treat CookieNotFoundException as success so decommission flows are idempotent","Monitor metadata store health before running decommission operations","Avoid running concurrent decommissions for the same bookie"],"tags":["metadata-store","bookkeeper","cookie","decommission"],"backgroundTag":"bookie-cookie-delete-failed","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}