apache/pulsar · warning · BookieException.MetadataStoreException

Interrupted deleting cookie for bookie

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.

Solutions

  1. Respect the interrupt: stop the current decommission/cleanup task; the interrupt flag has been re-set so downstream code will also see it.
  2. Re-run the decommission command after the environment is stable — removeCookie is safe to retry if the cookie still exists.
  3. Fix lifecycle ordering so cookie deletion completes before the executor/process begins shutting down.
  4. 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

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


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

Appendix: 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 exists

View on GitHub (pinned to 820761864e)