apache/pulsar · error · RuntimeException
failed to get client token
Error message
failed to get client token
What it means
AuthenticationDataToken.getToken() invokes its tokenSupplier and wraps any Throwable in RuntimeException("failed to get client token", t). getToken backs getCommandData(), so every protocol command that needs the bearer token re-evaluates the supplier; any failure inside it (file read, secret lookup, NPE on a null supplier result) surfaces as this runtime exception.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationDataToken.java:64
public Set<Map.Entry<String, String>> getHttpHeaders() {
return this.headers.entrySet();
}
@Override
public boolean hasDataFromCommand() {
return true;
}
@Override
public String getCommandData() {
return getToken();
}
private String getToken() {
try {
return tokenSupplier.get();
} catch (Throwable t) {
throw new RuntimeException("failed to get client token", t);
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Inspect the wrapped cause (getCause()) to find why the supplier failed (missing file, null token, secret lookup error).
- Ensure the token source is available and returns a valid non-blank JWT before/while the client runs.
- For file-based tokens, verify the token file path exists and is readable at runtime, not just at startup.
- Harden custom token suppliers to throw descriptive exceptions and never return null.
Example fix
// before
Supplier<String> supplier = () -> Files.exists(path) ? readToken(path) : null; // null -> NPE wrapped as this error
// after
Supplier<String> supplier = () -> {
if (!Files.isReadable(path)) throw new IllegalStateException("token file missing: " + path);
return readToken(path);
}; Defensive patterns
Strategy: try-catch
Validate before calling
Supplier<String> safeSupplier = () -> {
String t = rawSupplier.get();
if (t == null || t.isBlank()) throw new IllegalStateException("token supplier produced a blank token");
return t;
}; Type guard
boolean isUsableToken(String t) { return t != null && t.split("\\.").length == 3; } // compact JWT Try / catch
try {
client = PulsarClient.builder().authentication(AuthenticationFactory.token(supplier))...create();
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("failed to get client token")) {
log.error("token supplier failed: {}", e.getCause(), e);
}
throw e;
} Prevention
- Wrap custom token suppliers to validate the token is non-null and looks like a JWT.
- Monitor/refresh token files and secrets so they remain readable while the client runs.
- Log e.getCause() to identify the real supplier failure (missing file, secret outage).
- Pre-authenticate once at startup so supplier failures surface before traffic.
When it happens
Trigger: The Supplier<String> passed to AuthenticationToken/AuthenticationDataToken throws: token file missing or unreadable, secret-manager lookup fails, supplier returns null and downstream code NPEs, or a static token string configured as invalid/blank causing parsing failure.
Common situations: Kubernetes secret rotated/deleted while the client is running; token file path from env var not set; vault/DynamicTokenSupplier outage; using AuthenticationToken with a function that returns null after expiry handling; authParams JSON missing the 'token' key so the supplier resolves to nothing.
Related errors
- No token credentials passed
- certFilePath must not be null
- keyFilePath must not be null
- certStream provider or stream must not be null
- keyStream provider or stream must not be null
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/011351682d0b85be.
Report an issue: GitHub.