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

  1. Verify the key URL is a well-formed file:/data: URI and the file contains valid Pulsar JSON key format (no PEM)
  2. Regenerate the key pair with Pulsar's tokens tool and re-encode the data URI correctly
  3. Check for config-value trimming/escaping issues (newlines, quotes) in application.properties
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/9df7e9396565be62. Report an issue: GitHub.