{"record":{"id":"50ddaf5022107fda","repo":"apache/pulsar","slug":"failed-to-get-client-token-50ddaf","errorCode":null,"errorMessage":"failed to get client token","messagePattern":"failed to get client token","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/v5/TokenAuthenticationV5.java","lineNumber":189,"sourceCode":"    @Override\n    public CompletableFuture<HttpAuthHeaders> getHttpHeadersAsync(HttpAuthCallContext ctx) {\n        return V5AuthContexts.supplyBlocking(blockingExecutor, () -> {\n            Map<String, String> headers = new LinkedHashMap<>();\n            headers.put(PULSAR_AUTH_METHOD_NAME, AUTH_METHOD_NAME);\n            headers.put(HTTP_HEADER_NAME, \"Bearer \" + token());\n            return HttpAuthHeaders.of(headers);\n        });\n    }\n\n    @Override\n    public void close() {\n    }\n\n    private String token() {\n        try {\n            return tokenSupplier.get();\n        } catch (Throwable t) {\n            throw new RuntimeException(\"failed to get client token\", t);\n        }\n    }\n}\n","sourceCodeStart":171,"sourceCodeEnd":193,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/v5/TokenAuthenticationV5.java#L171-L193","documentation":"TokenAuthenticationV5.token() fetches the token through a pluggable Supplier. Any Throwable thrown by the supplier (file read failure, parse error, static token code path failure) is caught and rethrown as a RuntimeException \"failed to get client token\" with the original cause attached.","triggerScenarios":"Calling the token() accessor when the configured tokenSupplier throws — e.g. the file-backed supplier hitting an IOException (see token-file error), or a custom supplier failing to fetch/refresh the token.","commonSituations":"Expired/rotated credential files disappearing at fetch time; custom token suppliers making network calls to a vault that is down; supplying a supplier that throws on first use because configuration was invalid.","solutions":["Inspect the wrapped cause (getCause()) to find the real failure and fix it (file path, network, credentials).","If using a file token, see the token file path/permissions fix; if using a custom supplier, harden it or add retry/caching logic.","Verify the token value itself is valid at configuration time (present, non-empty) so the supplier never throws for trivial reasons."],"exampleFix":"// before\nSupplier<String> s = () -> vaultClient.fetch(); // throws on outage\n// after\nSupplier<String> s = () -> {\n    try { return vaultClient.fetch(); }\n    catch (Exception e) { return cachedToken.orElseThrow(() -> e); }\n};","handlingStrategy":"try-catch","validationCode":"// dry-run the supplier before client startup\nString probe;\ntry { probe = tokenSupplier.get(); } catch (Throwable t) {\n    throw new IllegalStateException(\"token supplier failed at startup\", t);\n}\nif (probe == null || probe.isEmpty()) throw new IllegalStateException(\"empty client token\");","typeGuard":null,"tryCatchPattern":"try {\n    String t = authenticationToken();\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().equals(\"failed to get client token\")) {\n        Throwable cause = e.getCause(); // inspect and remediate the real failure\n    } else throw e;\n}","preventionTips":["Probe the token supplier once at startup so failures surface early with clear context.","Always inspect getCause() — the RuntimeException only wraps the real problem.","Make custom suppliers idempotent and retry-safe (cache last good token)."],"tags":["token-auth","supplier","wrapped-exception","configuration"],"backgroundTag":"client-token-fetch-failed","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}