{"record":{"id":"819f7b9b15a50f73","repo":"apache/pulsar","slug":"unsupported-request-body-type-body-getclass-g","errorCode":null,"errorMessage":"Unsupported request body type: ${body.getClass().getName}","messagePattern":"Unsupported request body type: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/v5/FrameworkHttpClient.java","lineNumber":142,"sourceCode":"\n    private org.asynchttpclient.Request toAhcRequest(HttpRequest request) {\n        RequestBuilder builder = new RequestBuilder(request.method().name())\n                .setUrl(request.uri().toString());\n        if (nameResolver != null) {\n            // Share the DNS resolver and its cache with the owning PulsarClient.\n            builder.setNameResolver(nameResolver);\n        }\n\n        request.headers().forEach(builder::setHeader);\n\n        request.body().ifPresent(body -> {\n            if (body instanceof HttpRequest.Bytes bytes) {\n                builder.setBody(bytes.content());\n                if (bytes.contentType() != null) {\n                    builder.setHeader(HttpHeaderNames.CONTENT_TYPE, bytes.contentType());\n                }\n            } else {\n                throw new IllegalArgumentException(\"Unsupported request body type: \" + body.getClass().getName());\n            }\n        });\n\n        return builder.build();\n    }\n\n    private CompletableFuture<HttpResponse> toHttpResponse(Response response) {\n        byte[] body = response.getResponseBodyAsBytes();\n        // Final guard only: BoundedResponseHandler already aborts the exchange while streaming.\n        if (body != null && body.length > config.maxResponseBodyBytes()) {\n            return CompletableFuture.failedFuture(new IOException(\n                    \"HTTP response body of \" + body.length + \" bytes exceeds the configured maximum of \"\n                            + config.maxResponseBodyBytes() + \" bytes\"));\n        }\n        Map<String, String> headers = new LinkedHashMap<>();\n        response.getHeaders().forEach(entry -> headers.put(entry.getKey(), entry.getValue()));\n        return CompletableFuture.completedFuture(HttpResponse.of(response.getStatusCode(), headers, body));\n    }","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/v5/FrameworkHttpClient.java#L124-L160","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nrequest = HttpRequest.newBuilder(uri).body(jsonString).build();\n// after\nrequest = HttpRequest.newBuilder(uri)\n        .body(new HttpRequest.Bytes(jsonString.getBytes(StandardCharsets.UTF_8), \"application/json\"))\n        .build();","handlingStrategy":"type-guard","validationCode":"// before execute()\nif (request.body() != null && !(request.body() instanceof HttpRequest.Bytes)) {\n    throw new IllegalArgumentException(\"body must be HttpRequest.Bytes\");\n}","typeGuard":"static boolean hasSupportedBody(PulsarHttpRequest r) {\n    return r.body() == null || r.body() instanceof HttpRequest.Bytes;\n}","tryCatchPattern":"try {\n    client.execute(request);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unsupported request body type\")) {\n        // rebuild request with HttpRequest.Bytes body\n    } else throw e;\n}","preventionTips":["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."],"tags":["http-client","illegal-argument","request-body","auth-v5"],"backgroundTag":"unsupported-request-body-type","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}