apache/pulsar · warning · BookieException.MetadataStoreException
Interrupted deleting cookie for bookie ${bookieId}
Error message
Interrupted deleting cookie for bookie ${bookieId} What it means
removeCookie performs a blocking store.delete(path, expectedVersion).get(timeout) on the asynchronous MetadataStore. If the waiting thread is interrupted, the manager restores the interrupt flag and throws BookieException.MetadataStoreException('Interrupted deleting cookie for bookie <bookieId>'). This happens during cookie cleanup (bookie decommission or format) and indicates the thread was interrupted, not that the delete itself failed or the cookie is missing.
Source
Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java:281
LongVersion version = new LongVersion(res.get().getStat().getVersion());
return new Versioned<>(res.get().getValue(), version);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new BookieException.MetadataStoreException(ie);
} 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 existsView on GitHub (pinned to 820761864e)
Solutions
- Respect the interrupt: stop the current decommission/cleanup task; the interrupt flag has been re-set so downstream code will also see it.
- Re-run the decommission command after the environment is stable — removeCookie is safe to retry if the cookie still exists.
- Fix lifecycle ordering so cookie deletion completes before the executor/process begins shutting down.
- If the metadata store is stalling (which makes long blocking waits likely), resolve the store latency first, then retry.
Example fix
// before
try {
regManager.removeCookie(bookieId, version);
} catch (BookieException e) {
log.info("ignoring", e); // swallows interrupt
}
// after
try {
regManager.removeCookie(bookieId, version);
} catch (BookieException.MetadataStoreException e) {
if (Thread.currentThread().isInterrupted()) {
Thread.currentThread().interrupt();
return; // abort cleanup, retry later
}
throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
regManager.removeCookie(bookieId, version);
} catch (BookieException.MetadataStoreException e) {
if (Thread.currentThread().isInterrupted()) {
// abort decommission gracefully; safe to rerun later
return;
}
throw e;
} Prevention
- Run decommission/format tasks to completion without interrupting the worker (avoid Ctrl-C and shutdownNow mid-delete).
- Sequence shutdown so cookie cleanup finishes before executors are torn down.
- Resolve metadata store stalls first — long blocking waits make interrupts from watchdogs likely.
- removeCookie is retryable: if interrupted, rerun the decommission once stable.
When it happens
Trigger: The thread blocked in removeCookie's .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS) is interrupted — typically during bookie shutdown/decommission while deleting the cookie, or a canceled admin/format task interrupting the worker thread.
Common situations: Decommissioning a bookie (bin/bookkeeper shell decommission) while the client/process is being shut down concurrently; MetadataStoreExpirer or format tooling run under an executor that gets shutDownNow; operator Ctrl-C during a long-running metadata-store stall.
Related errors
- Interrupted writing cookie for bookie ${bookieId}
- Failed to delete cookie for bookie ${bookieId}
- Invalid version type, expected it to be LongVersion
- Failed to write cookie for bookie ${bookieId}
- METADATA_SERVICE_ERROR
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/19122b3d35c965ad.
Report an issue: GitHub.