apache/pulsar · error · RestException
Invalid number of bundles. Number of bundles has to be in th
Error message
Invalid number of bundles. Number of bundles has to be in the range of (0, 2^32].
What it means
PoliciesUtil.getBundles(numBundles) computes the namespace bundle boundaries by dividing the full 32-bit hash range by numBundles. A count of zero or negative makes that division meaningless (and would divide by zero), so the method rejects it with a 400-style RestException before any bundle data is built.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/PoliciesUtil.java:54
boundaries.add(LAST_BOUNDARY);
return BundlesData.builder()
.numBundles(1)
.boundaries(boundaries)
.build();
}
public static void setStorageQuota(Policies polices, BacklogQuota quota) {
if (polices == null) {
return;
}
polices.backlog_quota_map.put(BacklogQuota.BacklogQuotaType.destination_storage, quota);
}
private static final long MAX_BUNDLES = ((long) 1) << 32;
public static BundlesData getBundles(int numBundles) {
if (numBundles <= 0) {
throw new RestException(Response.Status.BAD_REQUEST,
"Invalid number of bundles. Number of bundles has to be in the range of (0, 2^32].");
}
Long maxVal = MAX_BUNDLES;
Long segSize = maxVal / numBundles;
List<String> partitions = new ArrayList<>();
partitions.add(String.format("0x%08x", 0L));
Long curPartition = segSize;
for (int i = 0; i < numBundles; i++) {
if (i != numBundles - 1) {
partitions.add(String.format("0x%08x", curPartition));
} else {
partitions.add(String.format("0x%08x", maxVal - 1));
}
curPartition += segSize;
}
return BundlesData.builder()
.boundaries(partitions)
.numBundles(numBundles)View on GitHub (pinned to 820761864e)
Solutions
- Pass a positive bundle count (1 is the minimum) to the namespace creation/update API
- Fix the calling script/config so the bundles value is not defaulted to 0
- Clamp or validate the value client-side before calling the admin API
- If you need more than 2^31 bundles, restructure the namespace instead
Example fix
// before admin.namespaces().createNamespace(namespace, 0); // throws // after int numBundles = Math.max(1, configuredBundles); admin.namespaces().createNamespace(namespace, numBundles);
Defensive patterns
Strategy: validation
Validate before calling
// Validate before calling any bundles API
if (numBundles <= 0 || numBundles > (1L << 32)) {
throw new IllegalArgumentException("numBundles must be in (0, 2^32], got " + numBundles);
} Type guard
static boolean isValidBundleCount(Integer n) {
return n != null && n > 0 && n <= (1L << 32);
} Try / catch
try {
admin.namespaces().createNamespace(ns, numBundles);
} catch (PulsarAdminException e) {
if (e.getStatusCode() == 400) {
log.warn("Invalid bundle count {} — falling back to default", numBundles);
admin.namespaces().createNamespace(ns, 4);
} else throw e;
} Prevention
- Never let bundle count default to 0; initialize config keys explicitly
- Validate numeric inputs from scripts/UI before admin calls
- Remember the practical limit is 2^32; typical values are small (e.g. 4–256)
- Clamp values read from external config with Math.max(1, v)
When it happens
Trigger: Any admin API path that sets bundle count for a namespace (e.g. setNamespaceBundlesNum, namespaces.createNamespace with bundles) with numBundles <= 0, or with a value that overflowed int.
Common situations: Passing an unset/0 default from tooling or scripts, parsing the bundles count from config where the key is missing and defaults to 0, or integer overflow when users specify > 2^31-1 bundles.
Related errors
- Input bundles do not cover the whole hash range. first:
- Required at least one property for the namespace, but found
- Timeout during delete operation
- Timeout during close operation
- Timeout during open-cursor operation
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/66c509a5401993bb.
Report an issue: GitHub.