apache/pulsar · error · RestException
Segment topic not found: ${segmentTopic}
Error message
Segment topic not found: ${segmentTopic} What it means
HTTP 404 thrown by the segment terminate endpoint when the segment topic resolves but is not loaded on any broker (getTopicIfExists returns empty). Segment topics are never auto-created, and terminate requires a live in-memory topic instance on the owning broker.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Segments.java:163
@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 the parent topic name", required = true)
@PathParam("topic") @Encoded String encodedTopic,
@Parameter(description = "Segment descriptor (e.g. 0000-7fff-1)", required = true)
@PathParam("descriptor") String descriptor,
@Parameter(description = "Whether leader broker redirected this call to this broker.")
@QueryParam("authoritative") @DefaultValue("false") boolean authoritative) {
validateNamespaceName(tenant, namespace);
TopicName segmentTopic = segmentTopicName(tenant, namespace, encodedTopic, descriptor);
validateSuperUserAccessAsync()
.thenCompose(__ -> validateTopicOwnershipAsync(segmentTopic, authoritative))
.thenCompose(__ -> pulsar().getBrokerService().getTopicIfExists(segmentTopic.toString()))
.thenCompose(optTopic -> {
if (optTopic.isEmpty()) {
throw new RestException(Response.Status.NOT_FOUND,
"Segment topic not found: " + segmentTopic);
}
if (optTopic.get() instanceof PersistentTopic pt) {
return pt.terminate().thenApply(__ -> null);
}
throw new RestException(Response.Status.BAD_REQUEST,
"Cannot terminate non-persistent topic: " + segmentTopic);
})
.thenAccept(__ -> {
log.info().attr("clientAppId", clientAppId()).attr("segment", segmentTopic)
.log("Terminated segment topic");
asyncResponse.resume(Response.noContent().build());
})
.exceptionally(ex -> {
log.error().attr("clientAppId", clientAppId()).attr("segment", segmentTopic)
.exception(ex).log("Failed to terminate segment topic");
resumeAsyncResponseExceptionally(asyncResponse, ex);
return null;View on GitHub (pinned to 820761864e)
Solutions
- Verify the segment topic name (hash range + segment id) against the scalable topic's metadata.
- Trigger load of the segment topic (e.g. produce/consume once or use the admin API to look it up) and retry termination.
- Confirm the segment still exists in the scalable topic metadata before terminating; if deleted, skip it.
Example fix
// before
await admin.scalableTopics().terminateSegment(segmentTopicName); // 404 not loaded
// after
const md = await admin.scalableTopics().getScalableTopicMetadataAsync(tenant, ns, topic);
if (md.getSegments().containsKey(segmentId)) {
await admin.scalableTopics().terminateSegment(segmentTopicName);
} Defensive patterns
Strategy: retry
Validate before calling
const md = await admin.scalableTopics().getScalableTopicMetadataAsync(tenant, ns, parentTopic);
if (!md.getSegments().containsKey(segmentId)) throw new Error('segment does not exist in metadata'); Type guard
const segmentIsKnown = (metadata, segId) => metadata?.getSegments?.().has(segId) ?? false;
Try / catch
try {
await admin.scalableTopics().terminateSegment(segmentTopic);
} catch (e) {
if (e.status === 404) { await sleep(loadRetryMs); return admin.scalableTopics().terminateSegment(segmentTopic); }
throw e;
} Prevention
- Build segment names from the scalable topic metadata (hash range + segment id), never by hand.
- Touch the segment (lookup/reader) to force load before terminating.
- Handle broker restarts/failovers by re-trying ownership-dependent calls.
When it happens
Trigger: Calling the terminateSegment REST endpoint for a segment whose topic has not been loaded/owned by this broker path — e.g. after broker restart, before first use, after the segment was deleted, or a wrong segment hash-range/segment-id in the composed segment name.
Common situations: Terminating a segment of a freshly created scalable topic whose segment topic was unloaded; race between segment deletion and a terminate call; mistyped segment topic name; broker ownership moved and the redirect/ownership check passed but load hadn't completed.
Related errors
- Segment topic not loaded: ${segmentTopic}
- Subscription not found on segment: ${subscription}
- Topic does not exist: ${persistentBase}
- Scalable topic not found: ${tn}
- Cannot terminate non-persistent topic: ${segmentTopic}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/29b958b1fbf58844.
Report an issue: GitHub.