apache/pulsar · error · BookieException.MetadataStoreException

Failed to write cookie for bookie ${bookieId}

Error message

Failed to write cookie for bookie ${bookieId}

What it means

This is writeCookie's generic failure path: the underlying MetadataStore put failed (an ExecutionException whose cause is NOT a BadVersionException), so the cookie could not be written for the bookie. The manager discards the cause here and throws BookieException.MetadataStoreException('Failed to write cookie for bookie <bookieId>') without it, meaning the real store-side error must be found in the store's own logs. It indicates a metadata-store connectivity, permission, session, or internal failure rather than a version conflict (which raises CookieExistException instead).

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java:246

                version = -1L;
            } else {
                if (!(cookieData.getVersion() instanceof LongVersion)) {
                    throw new BookieException.BookieIllegalOpException(
                            "Invalid version type, expected it to be LongVersion");
                }
                version = ((LongVersion) cookieData.getVersion()).getLongVersion();
            }

            store.put(path, cookieData.getValue(), Optional.of(version))
                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
            throw new BookieException.MetadataStoreException("Interrupted writing cookie for bookie " + bookieId, ie);
        } catch (ExecutionException e) {
            if (e.getCause() instanceof MetadataStoreException.BadVersionException) {
                throw new BookieException.CookieExistException(bookieId.toString());
            } else {
                throw new BookieException.MetadataStoreException("Failed to write cookie for bookie " + bookieId);
            }
        } catch (TimeoutException ex) {
            throw new BookieException.MetadataStoreException("Failed to write cookie for bookie " + bookieId, ex);
        }
    }

    @Override
    public Versioned<byte[]> readCookie(BookieId bookieId) throws BookieException {
        String path = this.cookiePath + "/" + bookieId;
        try {
            Optional<GetResult> res = store.get(path).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
            if (!res.isPresent()) {
                throw new BookieException.CookieNotFoundException(bookieId.toString());
            }

            // sets stat version from MetadataStore
            LongVersion version = new LongVersion(res.get().getStat().getVersion());
            return new Versioned<>(res.get().getValue(), version);

View on GitHub (pinned to 820761864e)

Solutions

  1. Check the metadata store's client/server logs for the underlying cause around this timestamp (the exception itself does not carry it).
  2. Verify metadataServiceUri connectivity and that the bookie's credentials allow writing under the cookie path (/ledgers/cookies).
  3. Restart the bookie once the metadata store is healthy — cookie writes are retried at startup.
  4. If failures are persistent, inspect store-side health: ZooKeeper ensemble, etcd cluster state, auth ACLs, and network paths.

Example fix

// before (server-side)
} else {
    throw new BookieException.MetadataStoreException("Failed to write cookie for bookie " + bookieId);
}

// after (preserve the cause for diagnosis)
} else {
    throw new BookieException.MetadataStoreException(
            "Failed to write cookie for bookie " + bookieId, e.getCause());
}
Defensive patterns

Strategy: retry

Validate before calling

// check metadata store reachability before cookie operations
store.exists(cookiePath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);

Try / catch

try {
    regManager.writeCookie(bookieId, cookie);
} catch (BookieException.MetadataStoreException e) {
    // cause is dropped server-side: check store logs, then retry with backoff
    if (!Thread.currentThread().isInterrupted() && attempts < MAX_ATTEMPTS) {
        Thread.sleep(BACKOFF_MS);
        regManager.writeCookie(bookieId, cookie);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: store.put(path, cookieData, Optional.of(version)) completes exceptionally with any cause other than MetadataStoreException.BadVersionException — e.g. connection loss, session expired, no auth/permission on the cookie z-node/prefix, or store-client internal error.

Common situations: Metadata service (ZooKeeper/etcd) unreachable or session expired while the bookie starts; wrong metadataServiceUri/credentials so writes to the /ledgers/cookies path are denied; metadata store read-only or quota exceeded; transient network partition during bookie bootstrap.

Related errors


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