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
- Check the metadata store's client/server logs for the underlying cause around this timestamp (the exception itself does not carry it).
- Verify metadataServiceUri connectivity and that the bookie's credentials allow writing under the cookie path (/ledgers/cookies).
- Restart the bookie once the metadata store is healthy — cookie writes are retried at startup.
- 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
- Monitor metadata store availability and quorum before/while bookies bootstrap.
- Verify metadataServiceUri, credentials, and ACLs grant write access to the cookie path.
- Prefer bookie auto-restart with backoff so transient store failures self-heal.
- Because the exception drops the cause, always correlate with metadata store client logs to find the real error.
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
- failed to init BookieId list
- Error contacting with metadata store
- Error contacting metadata store
- Error while getting ReplicationWorkerId rereplicating Ledger
- Invalid version type, expected it to be LongVersion
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/14a8330025ae0ce4.
Report an issue: GitHub.