apache/pulsar · info · RestException
cluster data is required
Error message
cluster data is required
What it means
createCluster validates that a ClusterData payload accompanies the PUT /admin/v2/clusters/{cluster} request. The cluster name comes from the path, but the body must contain the cluster configuration (service URLs, etc.); if the body is missing, null, or deserializes to null, it throws HTTP 400 BAD_REQUEST with 'cluster data is required'.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ClustersBase.java:174
required = true,
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
examples = @ExampleObject(
value = """
{
"serviceUrl": "http://pulsar.example.com:8080",
"brokerServiceUrl": "pulsar://pulsar.example.com:6651"
}
"""
)
)
) ClusterDataImpl clusterData) {
validateBothSuperuserAndClusterOperation(cluster, ClusterOperation.CREATE_CLUSTER)
.thenCompose(__ -> validatePoliciesReadOnlyAccessAsync())
.thenCompose(__ -> {
NamedEntity.checkName(cluster);
if (clusterData == null) {
throw new RestException(Status.BAD_REQUEST, "cluster data is required");
}
try {
clusterData.checkPropertiesIfPresent();
} catch (IllegalArgumentException ex) {
throw new RestException(Status.BAD_REQUEST, ex.getMessage());
}
return clusterResources().getClusterAsync(cluster);
}).thenCompose(clusterOpt -> {
if (clusterOpt.isPresent()) {
throw new RestException(Status.CONFLICT, "Cluster already exists");
}
return clusterResources().createClusterAsync(cluster, clusterData);
}).thenAccept(__ -> {
log.info().attr("cluster", cluster).log("Created cluster");
asyncResponse.resume(Response.ok().build());
}).exceptionally(ex -> {
log.error()
.attr("cluster", cluster)View on GitHub (pinned to 820761864e)
Solutions
- Send a complete ClusterData JSON body, e.g. {"serviceUrl":"http://broker:8080","serviceUrlTls":"https://broker:8443","brokerServiceUrl":"pulsar://broker:6650","brokerServiceUrlTls":"pulsar+ssl://broker:6651"}.
- Ensure the request Content-Type is application/json and the body is non-empty; with curl use -H 'Content-Type: application/json' -d '{...}'.
- Prefer the Java/CLI client (pulsar-admin clusters create) which constructs ClusterData for you, avoiding hand-rolled REST bodies.
Example fix
// before: empty body -> 400
curl -X PUT http://broker:8080/admin/v2/clusters/us-west -H 'Content-Type: application/json'
// after: supply cluster data
curl -X PUT http://broker:8080/admin/v2/clusters/us-west -H 'Content-Type: application/json' \
-d '{"serviceUrl":"http://broker:8080","brokerServiceUrl":"pulsar://broker:6650"}' Defensive patterns
Strategy: validation
Validate before calling
// validate the payload before PUT /clusters/{cluster}
if (clusterData == null || clusterData.getServiceUrl() == null
|| clusterData.getServiceUrl().isEmpty()) {
throw new IllegalArgumentException("cluster data with serviceUrl is required");
} Try / catch
try {
admin.clusters().createCluster(clusterName, clusterData);
} catch (PulsarAdminException.BadRequestException e) {
if ("cluster data is required".equals(e.getMessage())) {
log.error("PUT sent without a ClusterData body");
}
} Prevention
- Always send a ClusterData JSON body (serviceUrl at minimum) when creating a cluster via REST.
- Set Content-Type: application/json on REST calls; verify with -v in curl that the body is transmitted.
- Prefer pulsar-admin clusters create or the Java admin client over raw REST to avoid payload mistakes.
When it happens
Trigger: PUT /admin/v2/clusters/{cluster} with an empty body, no Content-Type/application-json, or a JSON body that deserializes to a null ClusterData object (e.g. literal 'null' body).
Common situations: Using curl without -d/--data or with an empty -d '{}'-less body; CLI/SDK calls where the cluster data argument is omitted; scripting against the REST API with wrong Content-Type so the body is dropped; proxy/gateway stripping the request body.
Related errors
- Invalid cluster id: ${clusterId}
- Clusters do not exist
- %s %s cannot be admitted:- %s
- Tenant is not provided
- Namespace is not provided
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/50c664e6370f3354.
Report an issue: GitHub.