quarkusio/quarkus · error · IOException
Invalid privateKey format
Error message
Invalid privateKey format
What it means
The substituted loadPrivateKey wraps URISyntaxException / InstantiationException / IllegalAccessException from parsing and reflecting the Pulsar key URL into an IOException with message 'Invalid privateKey format', signaling the privateKey URL could not be opened or its content parsed as a JSON KeyFile in native mode.
Source
Thrown at extensions/smallrye-reactive-messaging-pulsar/runtime/src/main/java/io/quarkus/pulsar/runtime/graal/Substitutions.java:51
private static KeyFile loadPrivateKey(String privateKeyURL) throws IOException {
try {
URLConnection urlConnection = new org.apache.pulsar.client.api.url.URL(privateKeyURL).openConnection();
try {
String protocol = urlConnection.getURL().getProtocol();
if ("data".equals(protocol) && !"application/json".equals(urlConnection.getContentType())) {
throw new IllegalArgumentException(
"Unsupported media type or encoding format: " + urlConnection.getContentType());
}
KeyFile privateKey;
try (Reader r = new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8)) {
privateKey = KeyFile.fromJson(r);
}
return privateKey;
} finally {
IOUtils.close(urlConnection);
}
} catch (URISyntaxException | InstantiationException | IllegalAccessException e) {
throw new IOException("Invalid privateKey format", e);
}
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Verify the key URL is a well-formed file:/data: URI and the file contains valid Pulsar JSON key format (no PEM)
- Regenerate the key pair with Pulsar's tokens tool and re-encode the data URI correctly
- Check for config-value trimming/escaping issues (newlines, quotes) in application.properties
- Load the key from a plain file path (file:) rather than an exotic URL scheme
Example fix
// before quarkus.native... authPrivateKey=-----BEGIN PRIVATE KEY-----... // after (valid Pulsar JSON key file) quarkus... authPrivateKey=file:/etc/pulsar/private-key.json
Defensive patterns
Strategy: validation
Validate before calling
static void validatePulsarKeyUrl(String keyUrl) throws IOException {
try {
new java.net.URI(keyUrl);
} catch (URISyntaxException e) {
throw new IOException("Malformed Pulsar key URL: " + keyUrl, e);
}
if (keyUrl.startsWith("data:")) {
String payload = new String(Base64.getDecoder().decode(keyUrl.substring(keyUrl.indexOf(",") + 1)), StandardCharsets.UTF_8);
if (!payload.trim().startsWith("{")) throw new IOException("Key is not Pulsar JSON format");
}
} Type guard
static boolean isWellFormedKeyUrl(String url) {
try { new java.net.URI(url); return true; } catch (URISyntaxException e) { return false; }
} Try / catch
try {
configurePulsarAuth(keyUrl);
} catch (PulsarClientException | IOException e) {
if (e.getMessage() != null && e.getMessage().contains("Invalid privateKey format")) {
throw new ConfigurationException("authPrivateKey/authPublicKey URL or content is invalid for native mode", e);
}
throw e;
} Prevention
- Validate key URLs and JSON structure at app startup, before client creation
- Avoid PEM keys; Pulsar expects its JSON KeyFile format
- Check application.properties for accidental line-wrapping or whitespace in the key value
- Test auth config in native mode early; substitutions behave differently than JVM mode
When it happens
Trigger: Passing a malformed authPrivateKey/authPublicKey URL to the Pulsar client in native mode: unparsable URIs, unsupported protocols, or corrupt/non-JSON key file contents causing KeyFile.fromJson to fail.
Common situations: Typo'd file: URLs, whitespace or newlines in base64 data URIs, PEM keys supplied where JSON keys are expected, keys truncated by config trimming.
Related errors
- Unsupported media type or encoding format: ${contentType}
- No configuration is available
- The fixed port must be greater than 0
- io_uring is not supported with Netty 4.2
- service interface name cannot be null or blank
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9df7e9396565be62.
Report an issue: GitHub.