apache/pulsar · error · AuthenticationException
NO_PUBLIC_KEY
NO_PUBLIC_KEY
Error message
Unable to retrieve ZTS Public Key
What it means
authenticate() asks the Athenz AuthZpeClient for the ZTS public key matching the token's keyId. If it returns null, errorCode NO_PUBLIC_KEY is set and this AuthenticationException is thrown: the broker cannot obtain the signing key needed to verify the token's signature, so verification cannot proceed.
Source
Thrown at pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java:155
.attr("clientAddress", clientAddress)
.log("Athenz RoleToken received from Client");
RoleToken token = new RoleToken(roleToken);
if (!domainNameList.contains(token.getDomain())) {
errorCode = ErrorCode.DOMAIN_MISMATCH;
throw new AuthenticationException(
String.format("Athenz RoleToken Domain mismatch, Expected: %s, Found: %s",
domainNameList.toString(), token.getDomain()));
}
// Synchronize for non-thread safe static calls inside athenz library
synchronized (this) {
PublicKey ztsPublicKey = AuthZpeClient.getZtsPublicKey(token.getKeyId());
if (ztsPublicKey == null) {
errorCode = ErrorCode.NO_PUBLIC_KEY;
throw new AuthenticationException("Unable to retrieve ZTS Public Key");
}
if (token.validate(ztsPublicKey, allowedOffset, false, null)) {
log.debug().attr("roleToken", roleToken)
.attr("clientAddress", clientAddress)
.log("Athenz Role Token Authenticated for Client");
authenticationMetrics.recordSuccess();
return token.getPrincipal();
} else {
errorCode = ErrorCode.INVALID_TOKEN;
throw new AuthenticationException(
String.format("Athenz Role Token Not Authenticated from Client: %s", clientAddress));
}
}
} catch (AuthenticationException exception) {
incrementFailureMetric(errorCode);
throw exception;
}View on GitHub (pinned to 820761864e)
Solutions
- Refresh the ZTS public key material on the broker (update athenz zts public key files/config) so the token's keyId resolves.
- Restart or re-initialize the provider to force AuthZpeClient to reload keys after ZTS rotation.
- Confirm the token comes from the same ZTS environment as the broker's configured keys (check keyId against your ZTS).
- Update the athenz client library so its key-refresh/caching behavior matches your ZTS rotation interval.
Example fix
// before # broker host has stale key /etc/athenz/zts_public_key.pem (old K_id, missing rotated key) // after # re-fetch from ZTS and install current keys wget https://zts.example.com:8443/zts/v1/publicKey -O /etc/athenz/zts_public_key.pem systemctl restart pulsar-broker
Defensive patterns
Strategy: retry
Validate before calling
// after provider init, sanity check key availability for expected keyIds
PublicKey k = AuthZpeClient.getZtsPublicKey(expectedKeyId);
if (k == null) { /* refresh zts public key files before serving traffic */ } Try / catch
try {
principal = provider.authenticate(authData);
} catch (AuthenticationException e) {
if (e.getMessage().contains("Unable to retrieve ZTS Public Key")) {
// refresh key material / reload provider, then retry once
}
throw e;
} Prevention
- Track ZTS key rotation and refresh broker public key files before old keys expire.
- Keep the athenz client library current so key caching handles rotation.
- Ensure brokers only accept tokens from the matching ZTS environment.
When it happens
Trigger: AuthZpeClient.getZtsPublicKey(token.getKeyId()) returns null because the keyId is unknown — the ZTS rotated keys and the broker's public key cache is stale, or the token was issued by a ZTS the broker has no key material for.
Common situations: Athenz ZTS key rotation without refreshing the broker's key files / zts public key config; clock-triggered cache expiry in AuthZpeClient; tokens issued by a different ZTS environment (dev vs prod); corrupted or outdated athenz.conf public key files on the broker host.
Related errors
- No athenz domain name specified
- Invalid allowed offset for athenz role token verification sp
- Allowed offset for athenz role token verification must not b
- NO_CLIENT
- NO_TOKEN
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b78992a3a9457711.
Report an issue: GitHub.