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

  1. Wrap the payload in HttpRequest.Bytes: pass body bytes via HttpRequest.Bytes with an optional contentType.
  2. If the body is a String, convert with getBytes(StandardCharsets.UTF_8) and set the Content-Type explicitly.
  3. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/819f7b9b15a50f73. Report an issue: GitHub.