apache/pulsar · error · IllegalArgumentException
Unsupported media type or encoding format: ${contentType}
Error message
Unsupported media type or encoding format: ${contentType} What it means
ClientCredentialsFlow.loadPrivateKey() opens a URL for the privateKey and, when the protocol is 'data', requires the content type to be application/json. A data: URI with any other content type is rejected with IllegalArgumentException('Unsupported media type or encoding format: ...') because the key file must be JSON (KeyFile.fromJson).
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/ClientCredentialsFlow.java:133
.jcaProvider(jcaProvider)
.build();
}
/**
* Loads the private key from the given URL.
*
* @param privateKeyURL
* @return
* @throws IOException
*/
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();
String contentType = urlConnection.getContentType();
if ("data".equals(protocol) && !"application/json".equals(contentType)) {
throw new IllegalArgumentException(
"Unsupported media type or encoding format: " + urlConnection.getContentType());
}
KeyFile privateKey;
try (Reader r = new InputStreamReader((InputStream) urlConnection.getContent(),
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);
}
}
@Override
public void initialize() throws PulsarClientException {View on GitHub (pinned to 820761864e)
Solutions
- Use a data URI with explicit JSON type: data:application/json;base64,<base64 of key json>
- Decode the key and pass a file:// or data:application/json URI
- Verify the URI encodes ';base64' correctly when the payload is base64
Example fix
// before String key = "data:text/plain;base64,eyJjbGllbnRJZCI6Ii4uLiJ9"; // after String key = "data:application/json;base64,eyJjbGllbnRJZCI6Ii4uLi4ifQ==";
Defensive patterns
Strategy: validation
Validate before calling
String key = authParams.get("privateKey");
if (key != null && key.startsWith("data:")) {
int semi = key.indexOf(';');
String type = key.substring(5, semi > 0 ? semi : key.length());
if (!"application/json".equals(type)) {
throw new IllegalArgumentException("data URI privateKey must be application/json, got: " + type);
}
} Type guard
boolean isJsonDataUri(String uri) {
return uri != null && uri.startsWith("data:application/json")
&& (uri.length() == "data:application/json".length()
|| uri.charAt("data:application/json".length()) == ';' || uri.charAt("data:application/json".length()) == ',');
} Try / catch
try {
flow.initialize();
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unsupported media type")) {
throw new ConfigException("Fix privateKey data URI to data:application/json;base64,...", e);
}
throw e;
} Prevention
- Always declare application/json in data: URIs for the private key
- Base64-encode the key JSON and include the ';base64' marker
- Test data URI decoding independently before wiring into the client
When it happens
Trigger: privateKey supplied as a data: URI whose declared media type is not application/json, e.g. data:text/plain;base64,... or data:;base64,...; the URI encoding drops or alters the content type.
Common situations: Embedding the OAuth2 key JSON as a data URI in config (common in Kubernetes secrets) with the wrong MIME type; hand-encoding the base64 payload and forgetting ';base64' or the type segment.
Related errors
- Malformed configuration parameter: earlyTokenRefreshPercent
- Invalid privateKey format
- Unable to read private key: ${message}
- Required configuration parameter: ${name}
- earlyTokenRefreshPercent must be greater than 0.
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/9d1ebd9ee8ef9a61.
Report an issue: GitHub.