apache/pulsar · error · BookieException.MetadataStoreException
Failed to delete cookie for bookie
Error message
Failed to delete cookie for bookie ${bookieId} What it means
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.
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
Example fix
// before registrationManager.removeCookie(bookieId, staleVersion); // after Versioned<byte[]> cookie = registrationManager.readBookieCookie(bookieId); registrationManager.removeCookie(bookieId, cookie.getVersion());
Defensive patterns
Strategy: try-catch
Validate before calling
// Java
MetadataStore store = ...;
if (!store.exists(cookiePath + "/" + bookieId).get(30, TimeUnit.SECONDS)) {
// cookie absent -> removeCookie is unnecessary
}
Type guard
boolean cookieExists(MetadataStore store, BookieId id) {
try {
return store.exists("/cookies/" + id).get(30, TimeUnit.SECONDS);
} catch (Exception e) { return false; }
}
Try / catch
try {
registrationManager.removeCookie(bookieId, version);
} catch (BookieException.CookieNotFoundException e) {
// already gone: idempotent success
} catch (BookieException.MetadataStoreException e) {
// check store health, re-read cookie for fresh Version, retry
}
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Interrupted deleting cookie for bookie
- Failed to write cookie for bookie
- Interrupted writing cookie for bookie
- Invalid version type, expected it to be LongVersion
- Error contacting metadata store
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/4209e9f8a43f5075.
Report an issue: GitHub.
Appendix: source
Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java:286
} catch (ExecutionException | TimeoutException e) {
throw new BookieException.MetadataStoreException(e);
}
}
@Override
public void removeCookie(BookieId bookieId, Version version) throws BookieException {
String path = this.cookiePath + "/" + bookieId;
try {
store.delete(path, Optional.of(((LongVersion) version).getLongVersion()))
.get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new BookieException.MetadataStoreException("Interrupted deleting cookie for bookie " + bookieId, e);
} catch (ExecutionException e) {
if (e.getCause() instanceof MetadataStoreException.NotFoundException) {
throw new BookieException.CookieNotFoundException(bookieId.toString());
} else {
throw new BookieException.MetadataStoreException("Failed to delete cookie for bookie " + bookieId);
}
} catch (TimeoutException ex) {
throw new BookieException.MetadataStoreException("Failed to delete cookie for bookie " + bookieId);
}
log.info().attr("cookiePath", cookiePath).attr("bookieId", bookieId).log("Removed cookie for bookie");
}
@Override
public boolean prepareFormat() throws Exception {
boolean ledgerRootExists = store.exists(ledgersRootPath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
boolean availableNodeExists = store.exists(bookieRegistrationPath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
// Create ledgers root node if not exists
if (!ledgerRootExists) {
store.put(ledgersRootPath, new byte[0], Optional.empty())
.get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
}
// create available bookies node if not existsView on GitHub (pinned to 820761864e)