apache/pulsar · warning · RestException

numInitialSegments must be >= 1

Error message

numInitialSegments must be >= 1

What it means

HTTP 412 thrown by the scalable-topic create REST endpoint when the query parameter numInitialSegments is less than 1. A scalable topic must be created with at least one initial segment, so zero or negative values are rejected as invalid configuration before any metadata is written.

Solutions

  1. Set the numInitialSegments query parameter to a value >= 1, or omit it (defaults to 1).
  2. Fix the calling script/tool so an unset value resolves to the default (1) rather than 0 or -1.
  3. Validate the segment count client-side before invoking the create call.

Example fix

// before
curl -X PUT '.../scalable-topics/tn/ns/my-topic?numInitialSegments=0'
// after
curl -X PUT '.../scalable-topics/tn/ns/my-topic?numInitialSegments=4'
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(numInitialSegments) || numInitialSegments < 1) {
  throw new Error('numInitialSegments must be an integer >= 1');
}

Type guard

const isValidSegmentCount = (n) => Number.isInteger(n) && n >= 1;

Try / catch

try {
  await admin.scalableTopics().createScalableTopic(tenant, ns, topic, numInitialSegments);
} catch (e) {
  if (e.status === 412) { /* fix segment count and retry */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling PUT /admin/v2/scalable-topics/{tenant}/{namespace}/{topic} with numInitialSegments=0 or a negative number.

Common situations: Automation scripts computing segment counts from an empty or misparsed config value; shell scripts omitting a default and passing 0; tools that pass -1 as a sentinel for 'unspecified' instead of omitting the parameter.

Understand the failure class

Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/ScalableTopics.java:189

            @Parameter(description = "Specify the tenant", required = true)
            @PathParam("tenant") String tenant,
            @Parameter(description = "Specify the namespace", required = true)
            @PathParam("namespace") String namespace,
            @Parameter(description = "Specify topic name", required = true)
            @PathParam("topic") @Encoded String encodedTopic,
            @Parameter(description = "Number of initial segments")
            @QueryParam("numInitialSegments") @DefaultValue("1") int numInitialSegments,
            @RequestBody(description = "Key value pair properties for the topic metadata")
            Map<String, String> properties) {
        validateNamespaceName(tenant, namespace);
        String decodedTopic = Codec.decode(encodedTopic);
        TopicName tn = TopicName.get(TopicDomain.topic.value(), namespaceName, decodedTopic);
        validateCreateTopic(tn);

        validateNamespaceOperationAsync(namespaceName, NamespaceOperation.CREATE_TOPIC)
                .thenCompose(__ -> {
                    if (numInitialSegments < 1) {
                        throw new RestException(Response.Status.fromStatusCode(412),
                                "numInitialSegments must be >= 1");
                    }
                    Map<String, String> props = properties != null ? properties : Map.of();
                    ScalableTopicMetadata metadata = ScalableTopicController.createInitialMetadata(
                            numInitialSegments,
                            pulsar().getConfiguration().getScalableTopicEntryBucketBudget(),
                            pulsar().getConfiguration().getScalableTopicEntryBucketMaxPerSegment(),
                            props);
                    return resources().createScalableTopicAsync(tn, metadata)
                            .thenCompose(ignored -> createInitialSegmentTopicsAsync(tn, metadata));
                })
                .thenAccept(__ -> {
                    log.info().attr("clientAppId", clientAppId()).attr("topic", tn)
                            .attr("numInitialSegments", numInitialSegments)
                            .log("Created scalable topic");
                    asyncResponse.resume(Response.noContent().build());
                })
                .exceptionally(ex -> {

View on GitHub (pinned to 820761864e)