apache/pulsar · error · IllegalArgumentException
Unsupported request body type: ${body.getClass().getName}
Error message
Unsupported request body type: ${body.getClass().getName} What it means
FrameworkHttpClient converts framework HTTP request objects into AsyncHttpClient (AHC) requests. When a request has a body, the library only knows how to serialize HttpRequest.Bytes payloads (raw byte arrays with an optional content type). Any other body representation is rejected with this IllegalArgumentException inside toAhcRequest, called from execute().
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/v5/FrameworkHttpClient.java:142
private org.asynchttpclient.Request toAhcRequest(HttpRequest request) {
RequestBuilder builder = new RequestBuilder(request.method().name())
.setUrl(request.uri().toString());
if (nameResolver != null) {
// Share the DNS resolver and its cache with the owning PulsarClient.
builder.setNameResolver(nameResolver);
}
request.headers().forEach(builder::setHeader);
request.body().ifPresent(body -> {
if (body instanceof HttpRequest.Bytes bytes) {
builder.setBody(bytes.content());
if (bytes.contentType() != null) {
builder.setHeader(HttpHeaderNames.CONTENT_TYPE, bytes.contentType());
}
} else {
throw new IllegalArgumentException("Unsupported request body type: " + body.getClass().getName());
}
});
return builder.build();
}
private CompletableFuture<HttpResponse> toHttpResponse(Response response) {
byte[] body = response.getResponseBodyAsBytes();
// Final guard only: BoundedResponseHandler already aborts the exchange while streaming.
if (body != null && body.length > config.maxResponseBodyBytes()) {
return CompletableFuture.failedFuture(new IOException(
"HTTP response body of " + body.length + " bytes exceeds the configured maximum of "
+ config.maxResponseBodyBytes() + " bytes"));
}
Map<String, String> headers = new LinkedHashMap<>();
response.getHeaders().forEach(entry -> headers.put(entry.getKey(), entry.getValue()));
return CompletableFuture.completedFuture(HttpResponse.of(response.getStatusCode(), headers, body));
}View on GitHub (pinned to 820761864e)
Solutions
- Wrap the payload in HttpRequest.Bytes: pass body bytes via HttpRequest.Bytes with an optional contentType.
- If the body is a String, convert with getBytes(StandardCharsets.UTF_8) and set the Content-Type explicitly.
- If no body is needed, leave the request body null instead of passing an empty wrapper object.
Example fix
// before
request = HttpRequest.newBuilder(uri).body(jsonString).build();
// after
request = HttpRequest.newBuilder(uri)
.body(new HttpRequest.Bytes(jsonString.getBytes(StandardCharsets.UTF_8), "application/json"))
.build(); Defensive patterns
Strategy: type-guard
Validate before calling
// before execute()
if (request.body() != null && !(request.body() instanceof HttpRequest.Bytes)) {
throw new IllegalArgumentException("body must be HttpRequest.Bytes");
} Type guard
static boolean hasSupportedBody(PulsarHttpRequest r) {
return r.body() == null || r.body() instanceof HttpRequest.Bytes;
} Try / catch
try {
client.execute(request);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unsupported request body type")) {
// rebuild request with HttpRequest.Bytes body
} else throw e;
} Prevention
- Always construct bodies via HttpRequest.Bytes with an explicit contentType.
- Add a small request-builder helper so raw body values never reach execute().
- Convert String payloads with a fixed charset instead of passing them directly.
When it happens
Trigger: Calling PulsarHttpClient.execute() with a request whose body() returns a non-HttpRequest.Bytes object (e.g. a String, InputStream, or custom BodyPublisher wrapper) instead of HttpRequest.Bytes.
Common situations: Custom authentication plugins built against the v5 HTTP framework that build requests manually and pass a String or JSON wrapper object as the body; code ported from java.net.http.HttpRequest (which accepts BodyPublisher) to the Pulsar framework HTTP client.
Related errors
- Positions must not be null
- Invalid range ${range}
- Split service unit should be split into 2 service units.
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/819f7b9b15a50f73.
Report an issue: GitHub.