apache/pulsar · error · IllegalArgumentException
Segment not found: ${segmentId}
Error message
Segment not found: ${segmentId} What it means
SegmentLayout.splitSegment applies a split to a segment identified by segmentId in the immutable layout map. If no segment with that id exists, an IllegalArgumentException is thrown, because splitting an unknown segment would corrupt the hash-range layout.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/scalable/SegmentLayout.java:168
}
toVisit.addAll(segment.parentIds());
}
return depth;
}
/**
* Produce a new layout by splitting a segment at its midpoint.
*
* @param segmentId the active segment to split
* @param nowMs wall-clock millis used as the parent's seal time and the
* children's create time. Caller passes a single value so
* CAS retries and follow-up reads agree.
* @return a new SegmentLayout with the split applied
*/
public SegmentLayout splitSegment(long segmentId, long nowMs) {
SegmentInfo segment = allSegments.get(segmentId);
if (segment == null) {
throw new IllegalArgumentException("Segment not found: " + segmentId);
}
if (!segment.isActive()) {
throw new IllegalArgumentException("Cannot split non-active segment: " + segmentId);
}
HashRange[] splitRanges = segment.hashRange().split();
long newEpoch = epoch + 1;
long childId1 = nextSegmentId;
long childId2 = nextSegmentId + 1;
// PIP-486: a split divides the parent's entry-buckets between its children — N/2 each (at least
// 1) — so the topic's total stays ≈ the budget as it fans out into more, narrower segments.
List<Integer> childEntryBucketSplits =
EntryBucketSplits.equalWidth(Math.max(1, segment.bucketCount() / 2));
SegmentInfo sealedParent = segment.sealed(newEpoch, nowMs, List.of(childId1, childId2));
SegmentInfo child1 = SegmentInfo.active(childId1, splitRanges[0],
List.of(segmentId), newEpoch, nowMs).withEntryBucketSplits(childEntryBucketSplits);
SegmentInfo child2 = SegmentInfo.active(childId2, splitRanges[1],View on GitHub (pinned to 820761864e)
Solutions
- Refresh to the latest SegmentLayout (e.g. via updated()) and re-resolve segment ids before splitting
- Validate segmentId exists via layout.allSegments.containsKey(id) (or equivalent) before calling
- Ensure split/merge coordination uses ids from the same layout epoch
Example fix
// before
layout.splitSegment(childIdFromOldSnapshot, now);
// after
SegmentLayout latest = updated();
if (latest.allSegments.containsKey(id)) { latest.splitSegment(id, now); } Defensive patterns
Strategy: validation
Validate before calling
if (!layout.allSegments.containsKey(segmentId)) {
throw new IllegalArgumentException("Unknown segmentId " + segmentId + "; valid: " + layout.allSegments.keySet());
} Type guard
boolean segmentExists(SegmentLayout layout, long segmentId) { return layout.allSegments.get(segmentId) != null; } Try / catch
try {
layout.splitSegment(id, now);
} catch (IllegalArgumentException e) {
log.warn("Split rejected: {} — refresh layout and retry with a valid id", e.getMessage());
} Prevention
- Always take segment ids from the latest layout snapshot
- Never reuse ids across epochs or after a merge
- Log layout epoch alongside ids to debug stale-snapshot races
When it happens
Trigger: Calling splitSegment with an id that was never created, an id from a different/older layout snapshot (stale epoch), or an already-removed (merged) segment id.
Common situations: Concurrent split/merge operations where a caller holds ids from a pre-merge layout; replaying recorded segment ids after layout replacement; test scaffolding using made-up ids.
Related errors
- Must have at least 1 segment
- Cannot split non-active segment: ${segmentId}
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
- Invalid key-shared mode: ${keySharedMode}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/2874df98fe7f046e.
Report an issue: GitHub.