{"record":{"id":"07e8f61267ab2aec","repo":"apache/pulsar","slug":"numinitialsegments-must-be-1","errorCode":null,"errorMessage":"numInitialSegments must be >= 1","messagePattern":"numInitialSegments must be >= 1","errorType":"http","errorClass":"RestException","httpStatus":412,"severity":"warning","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/ScalableTopics.java","lineNumber":189,"sourceCode":"            @Parameter(description = \"Specify the tenant\", required = true)\n            @PathParam(\"tenant\") String tenant,\n            @Parameter(description = \"Specify the namespace\", required = true)\n            @PathParam(\"namespace\") String namespace,\n            @Parameter(description = \"Specify topic name\", required = true)\n            @PathParam(\"topic\") @Encoded String encodedTopic,\n            @Parameter(description = \"Number of initial segments\")\n            @QueryParam(\"numInitialSegments\") @DefaultValue(\"1\") int numInitialSegments,\n            @RequestBody(description = \"Key value pair properties for the topic metadata\")\n            Map<String, String> properties) {\n        validateNamespaceName(tenant, namespace);\n        String decodedTopic = Codec.decode(encodedTopic);\n        TopicName tn = TopicName.get(TopicDomain.topic.value(), namespaceName, decodedTopic);\n        validateCreateTopic(tn);\n\n        validateNamespaceOperationAsync(namespaceName, NamespaceOperation.CREATE_TOPIC)\n                .thenCompose(__ -> {\n                    if (numInitialSegments < 1) {\n                        throw new RestException(Response.Status.fromStatusCode(412),\n                                \"numInitialSegments must be >= 1\");\n                    }\n                    Map<String, String> props = properties != null ? properties : Map.of();\n                    ScalableTopicMetadata metadata = ScalableTopicController.createInitialMetadata(\n                            numInitialSegments,\n                            pulsar().getConfiguration().getScalableTopicEntryBucketBudget(),\n                            pulsar().getConfiguration().getScalableTopicEntryBucketMaxPerSegment(),\n                            props);\n                    return resources().createScalableTopicAsync(tn, metadata)\n                            .thenCompose(ignored -> createInitialSegmentTopicsAsync(tn, metadata));\n                })\n                .thenAccept(__ -> {\n                    log.info().attr(\"clientAppId\", clientAppId()).attr(\"topic\", tn)\n                            .attr(\"numInitialSegments\", numInitialSegments)\n                            .log(\"Created scalable topic\");\n                    asyncResponse.resume(Response.noContent().build());\n                })\n                .exceptionally(ex -> {","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/ScalableTopics.java#L171-L207","documentation":"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.","triggerScenarios":"Calling PUT /admin/v2/scalable-topics/{tenant}/{namespace}/{topic} with numInitialSegments=0 or a negative number.","commonSituations":"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.","solutions":["Set the numInitialSegments query parameter to a value >= 1, or omit it (defaults to 1).","Fix the calling script/tool so an unset value resolves to the default (1) rather than 0 or -1.","Validate the segment count client-side before invoking the create call."],"exampleFix":"// before\ncurl -X PUT '.../scalable-topics/tn/ns/my-topic?numInitialSegments=0'\n// after\ncurl -X PUT '.../scalable-topics/tn/ns/my-topic?numInitialSegments=4'","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(numInitialSegments) || numInitialSegments < 1) {\n  throw new Error('numInitialSegments must be an integer >= 1');\n}","typeGuard":"const isValidSegmentCount = (n) => Number.isInteger(n) && n >= 1;","tryCatchPattern":"try {\n  await admin.scalableTopics().createScalableTopic(tenant, ns, topic, numInitialSegments);\n} catch (e) {\n  if (e.status === 412) { /* fix segment count and retry */ }\n  throw e;\n}","preventionTips":["Never pass 0/-1 as 'unspecified'; omit the parameter so the default (1) applies.","Centralize scalable-topic creation in a helper that clamps/validates the segment count.","Read the value from config with an explicit fallback, e.g. cfg.numSegments ?? 1."],"tags":["rest","validation","scalable-topics","http-412"],"backgroundTag":"invalid-parameter-value","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}