{"record":{"id":"b46e9f368bf0bab7","repo":"apache/pulsar","slug":"unable-to-read-private-key-message","errorCode":null,"errorMessage":"Unable to read private key: ${message}","messagePattern":"Unable to read private key: (.+?)","errorType":"exception","errorClass":"PulsarClientException.AuthenticationException","httpStatus":null,"severity":"critical","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/ClientCredentialsFlow.java","lineNumber":166,"sourceCode":"    }\n\n    @Override\n    public void initialize() throws PulsarClientException {\n        super.initialize();\n        assert this.metadata != null;\n\n        URL tokenUrl = this.metadata.getTokenEndpoint();\n        this.exchanger = new TokenClient(tokenUrl, getHttpClient());\n        initialized = true;\n    }\n\n    public TokenResult authenticate() throws PulsarClientException {\n        // read the private key from storage\n        KeyFile keyFile;\n        try {\n            keyFile = loadPrivateKey(this.privateKey);\n        } catch (IOException e) {\n            throw new PulsarClientException.AuthenticationException(\"Unable to read private key: \" + e.getMessage());\n        }\n\n        // request an access token using client credentials\n        ClientCredentialsExchangeRequest req = ClientCredentialsExchangeRequest.builder()\n                .clientId(keyFile.getClientId())\n                .clientSecret(keyFile.getClientSecret())\n                .audience(this.audience)\n                .scope(this.scope)\n                .authMethod(TokenEndpointAuthMethod.CLIENT_SECRET_POST)\n                .build();\n        TokenResult tr;\n        if (!initialized) {\n            initialize();\n        }\n        try {\n            tr = this.exchanger.exchangeClientCredentials(req);\n        } catch (TokenExchangeException | IOException e) {\n            throw new PulsarClientException.AuthenticationException(\"Unable to obtain an access token: \"","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/ClientCredentialsFlow.java#L148-L184","documentation":"authenticate() reads the private key file before requesting a token; any IOException from loadPrivateKey (unreadable location, bad URI, malformed wrapper) becomes PulsarClientException.AuthenticationException('Unable to read private key: <cause message>'). It signals the client never got far enough to attempt the token exchange.","triggerScenarios":"privateKey file path does not exist or is not readable; data: URI payload is not valid JSON so KeyFile.fromJson throws and surfaces as an IO failure; permissions deny reading the secret file.","commonSituations":"Kubernetes secret mounted at a different path than configured; JSON key file corrupted or truncated; typo in privateKey parameter; missing IAM permissions on cloud storage backends.","solutions":["Verify the privateKey URL/path exists and is readable by the client process","Validate the key file is well-formed JSON containing clientId/clientSecret","Check file permissions or mount configuration for the secret"],"exampleFix":"// before\nauthParams.put(\"privateKey\", \"file:///etc/pulsar/auth/old-key.json\"); // file deleted\n// after\nauthParams.put(\"privateKey\", \"file:///etc/pulsar/auth/client_credentials.json\"); // verified exists + readable","handlingStrategy":"validation","validationCode":"String key = authParams.get(\"privateKey\");\nif (key != null && key.startsWith(\"file:\")) {\n    java.nio.file.Path p = java.nio.file.Paths.get(java.net.URI.create(key));\n    if (!java.nio.file.Files.isReadable(p)) {\n        throw new IllegalStateException(\"privateKey file not readable: \" + p);\n    }\n    try (var in = java.nio.file.Files.newInputStream(p)) {\n        new String(in.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8).trim(); // ensure non-empty\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    flow.initialize();\n} catch (PulsarClientException.AuthenticationException e) {\n    if (e.getMessage().startsWith(\"Unable to read private key\")) {\n        // inspect cause: fix path/permissions/JSON, then recreate the auth\n        throw new ConfigException(\"Check privateKey path, permissions and JSON content: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Verify the key file path, mount and permissions in the deployment before startup","Validate the key JSON parses (contains clientId/clientSecret) in a preflight check","Avoid editing/rotating the key file while the client may re-read it; use atomic file replacement"],"tags":["oauth2","auth","file-io","config"],"backgroundTag":"private-key-unreadable","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"}