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

  1. Pass a positive bundle count (1 is the minimum) to the namespace creation/update API
  2. Fix the calling script/config so the bundles value is not defaulted to 0
  3. Clamp or validate the value client-side before calling the admin API
  4. 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

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


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