apache/pulsar · error · IllegalArgumentException

Must have at least 1 segment

Error message

Must have at least 1 segment

What it means

ScalableTopicController.createInitialMetadata builds the bootstrap SegmentLayout metadata for a new scalable topic, dividing the full hash range into numInitialSegments equal ranges. Fewer than 1 segment is nonsensical (division by zero / empty layout), so an IllegalArgumentException is thrown.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/scalable/ScalableTopicController.java:1555

     */
    public static ScalableTopicMetadata createInitialMetadata(int numInitialSegments,
                                                        int entryBucketBudget,
                                                        Map<String, String> properties) {
        return createInitialMetadata(numInitialSegments, entryBucketBudget,
                EntryBucketSplits.MAX_BUCKETS, properties);
    }

    /**
     * As {@link #createInitialMetadata(int, int, Map)}, clamping each initial segment's
     * budget-derived entry-bucket count to {@code maxBucketsPerSegment} (the configured
     * per-segment ceiling — the budget is a dynamic setting and must not exceed it).
     */
    public static ScalableTopicMetadata createInitialMetadata(int numInitialSegments,
                                                        int entryBucketBudget,
                                                        int maxBucketsPerSegment,
                                                        Map<String, String> properties) {
        if (numInitialSegments < 1) {
            throw new IllegalArgumentException("Must have at least 1 segment");
        }

        int rangeSize = (HashRange.MAX_HASH + 1) / numInitialSegments;
        Map<Long, SegmentInfo> segments = new LinkedHashMap<>();

        // PIP-486: share the topic's entry-bucket budget equally across the initial segments.
        List<Integer> entryBucketSplits = EntryBucketSplits.equalWidth(
                Math.min(EntryBucketSplits.bucketsForBudget(entryBucketBudget, numInitialSegments),
                        maxBucketsPerSegment));

        long nowMs = System.currentTimeMillis();
        for (int i = 0; i < numInitialSegments; i++) {
            int start = i * rangeSize;
            int end = (i == numInitialSegments - 1) ? HashRange.MAX_HASH : (start + rangeSize - 1);
            HashRange range = HashRange.of(start, end);
            SegmentInfo segment = SegmentInfo.active(i, range, 0, nowMs)
                    .withEntryBucketSplits(entryBucketSplits);
            segments.put((long) i, segment);

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure numInitialSegments >= 1 before calling createInitialMetadata
  2. Fix the source config/property feeding numInitialSegments and give it a sane default (e.g. 1 or 4)
  3. Add a caller-side guard or clamp: Math.max(1, configuredValue)

Example fix

// before
int numInitialSegments = Integer.parseInt(props.getProperty("initialSegments")); // null -> 0
// after
int numInitialSegments = Math.max(1, Integer.parseInt(props.getProperty("initialSegments", "1")));
Defensive patterns

Strategy: validation

Validate before calling

int n = configuredInitialSegments();
if (n < 1) throw new IllegalArgumentException("numInitialSegments must be >= 1, got " + n);
ScalableTopicController.createInitialMetadata(n, budget, maxBuckets, props);

Try / catch

try {
    metadata = ScalableTopicController.createInitialMetadata(n, budget, maxBuckets, props);
} catch (IllegalArgumentException e) {
    log.error("Bad initial segment count: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling createInitialMetadata with numInitialSegments < 1 (0, negative) when creating initial topic metadata.

Common situations: Config value for initial segments read from properties with a typo or unset so it defaults to 0; computation like totalRanges/hashRangeSize rounding to 0.

Understand the failure class

Background: "Invalid configuration value" and "Unsupported/Unknown setting value" errors: why libraries reject your config strings, numbers, and types — this error's family across 30 libraries.

Related errors


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