quarkusio/quarkus · error · IllegalArgumentException

Unsupported media type or encoding format: ${contentType}

Error message

Unsupported media type or encoding format: ${contentType}

What it means

A Graal substitution replacing Pulsar's KeyFileLoader private-key loading for native compatibility. When the key URL uses the 'data:' protocol, the substitution only accepts application/json content type and throws IllegalArgumentException for any other media type, since data URIs must carry the JSON key file.

Source

Thrown at extensions/smallrye-reactive-messaging-pulsar/runtime/src/main/java/io/quarkus/pulsar/runtime/graal/Substitutions.java:39

final class Target_com_scurrilous_circe_checksum_Crc32cIntChecksum {

    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias)
    @Alias
    private static IntHash CRC32C_HASH = new Java8IntHash();

}

@TargetClass(className = "org.apache.pulsar.client.impl.auth.oauth2.ClientCredentialsFlow")
final class Target_org_apache_pulsaR_client_impl_auth_oauth2_ClientCredentialsFlow {

    @Substitute
    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. Use data:application/json;base64,<base64-encoded JSON key file> for the key URI
  2. Store the key in a file and reference it via file: URL instead of a data URI
  3. Verify the data URI media type matches application/json exactly

Example fix

// before
String key = "data:text/plain;base64," + Base64.getEncoder().encodeToString(jsonKeyBytes);
// after
String key = "data:application/json;base64," + Base64.getEncoder().encodeToString(jsonKeyBytes);
Defensive patterns

Strategy: validation

Validate before calling

static String toValidKeyDataUri(Path jsonKeyFile) throws IOException {
    byte[] bytes = Files.readAllBytes(jsonKeyFile);
    return "data:application/json;base64," + Base64.getEncoder().encodeToString(bytes);
}
// call before configuring the client: ensure the file parses as JSON
new String(bytes, StandardCharsets.UTF_8).trim().startsWith("{");

Type guard

static boolean isValidJsonDataUri(String uri) {
    return uri != null && uri.startsWith("data:application/json");
}

Try / catch

try {
    client = PulsarClient.builder().serviceUrl(url)
        .auth(AuthenticationFactory.token(...))
        .authentication(AuthenticationTLS).build();
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Unsupported media type")) {
        throw new ConfigurationException("Key data: URI must use media type application/json", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring a Pulsar client token/key pair with a data: URI whose media type is not application/json (e.g. data:text/plain;base64,...) for authPrivateKey/authPublicKey in native mode.

Common situations: Embedding base64 private keys in config using data:text/plain or data:application/x-pem-file URIs; hand-built data URIs missing the application/json type.

Related errors


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