apache/pulsar · error · BookieException.MetadataStoreException

Failed to delete cookie for bookie ${bookieId}

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.

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 exists

View on GitHub (pinned to 820761864e)

Solutions

  1. Check metadata store connectivity/health (ZooKeeper/Oxia) before retrying removeCookie
  2. 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
  3. Verify the bookie id and cookie path are correct and no concurrent decommission is running
  4. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/4209e9f8a43f5075. Report an issue: GitHub.