apache/pulsar · critical · IllegalArgumentException
Failed to load private key from privateKey or privateKeyPath
Error message
Failed to load private key from privateKey or privateKeyPath field
What it means
After parsing authParams, setAuthParams resolves the private key from either the privateKey or privateKeyPath field. If both fields are absent/blank, or loadPrivateKey returns null (unreadable/unparseable key), AuthenticationAthenz throws IllegalArgumentException('Failed to load private key from privateKey or privateKeyPath field').
Source
Thrown at pulsar-client-auth-athenz/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationAthenz.java:239
if (isNotBlank(authParams.get("x509CertChain"))) {
// When using Copper Argos
checkRequiredParams(authParams, "privateKey", "caCert", "providerDomain");
// Absolute paths are required to generate a key refresher, so if these are relative paths, convert them
this.x509CertChainPath = getAbsolutePathFromUrl(authParams.get("x509CertChain"));
this.privateKeyPath = getAbsolutePathFromUrl(authParams.get("privateKey"));
this.caCertPath = getAbsolutePathFromUrl(authParams.get("caCert"));
} else {
checkRequiredParams(authParams, "tenantDomain", "tenantService", "providerDomain");
// privateKeyPath is deprecated, this is for compatibility
if (isBlank(authParams.get("privateKey")) && isNotBlank(authParams.get("privateKeyPath"))) {
this.privateKey = loadPrivateKey(authParams.get("privateKeyPath"));
} else {
this.privateKey = loadPrivateKey(authParams.get("privateKey"));
}
if (this.privateKey == null) {
throw new IllegalArgumentException(
"Failed to load private key from privateKey or privateKeyPath field");
}
}
if (isNotBlank(authParams.get("athenzConfPath"))) {
System.setProperty("athenz.athenz_conf", authParams.get("athenzConfPath"));
}
if (isNotBlank(authParams.get("principalHeader"))) {
System.setProperty("athenz.auth.principal.header", authParams.get("principalHeader"));
}
if (isNotBlank(authParams.get("roleHeader"))) {
this.roleHeader = authParams.get("roleHeader");
System.setProperty("athenz.auth.role.header", this.roleHeader);
}
if (isNotBlank(authParams.get("ztsUrl"))) {
this.ztsUrl = authParams.get("ztsUrl");
}
if (isNotBlank(authParams.get("ztsProxyUrl"))) {View on GitHub (pinned to 820761864e)
Solutions
- Add a valid 'privateKey' entry (e.g. 'data:application/x-pem-file;base64,<key>') or a 'privateKeyPath' file URL ('file:///path/to/key.pem') to authParams
- Verify the referenced file/URL exists and contains a parseable PEM private key
- Check JSON key spelling — must be exactly 'privateKey' or 'privateKeyPath'
Example fix
// before
{"tenant":"t","service":"s"}
// after
{"tenant":"t","service":"s","privateKeyPath":"file:///etc/pulsar/athenz_priv_key.pem"} Defensive patterns
Strategy: validation
Validate before calling
Map<String,String> params = new ObjectMapper().readValue(json, new TypeReference<Map<String,String>>(){});
String key = params.getOrDefault("privateKey", params.get("privateKeyPath"));
if (key == null || key.isBlank()) {
throw new IllegalArgumentException("athenz authParams needs 'privateKey' or 'privateKeyPath'");
}
if (key.startsWith("file:")) {
if (!Files.isReadable(Paths.get(URI.create(key)))) throw new IllegalArgumentException("key file missing/unreadable");
} Type guard
boolean hasPrivateKey(Map<String,String> p) {
return p.containsKey("privateKey") || p.containsKey("privateKeyPath");
} Try / catch
try {
authentication.configure(authParamsJson);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Failed to load private key")) {
log.error("Check 'privateKey'/'privateKeyPath' in authParams and that the key file exists");
}
throw e;
} Prevention
- Verify the key file exists and is readable by the process user at startup
- Use exact JSON key names: 'privateKey' and 'privateKeyPath'
- Prefer file:/// URLs in 'privateKeyPath' over hand-built data: URIs unless base64 is verified
When it happens
Trigger: configure() called with JSON missing both 'privateKey' and 'privateKeyPath' entries, or with values that loadPrivateKey cannot resolve (bad URL scheme, missing file, unparseable PEM).
Common situations: Athenz config copied from docs with placeholder paths; key file moved or deleted; typos like 'privatekey' or 'private_key' in the JSON keys; key data URI missing the data: prefix.
Related errors
- Failed to parse authParams
- Invalid URL format
- Unsupported media type or encoding format:
- Invalid privateKey format
- Cannnot get absolute path from specified URL
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/82f0e5136c134ca7.
Report an issue: GitHub.