{"record":{"id":"2874df98fe7f046e","repo":"apache/pulsar","slug":"segment-not-found-segmentid","errorCode":null,"errorMessage":"Segment not found: ${segmentId}","messagePattern":"Segment not found: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/service/scalable/SegmentLayout.java","lineNumber":168,"sourceCode":"            }\n            toVisit.addAll(segment.parentIds());\n        }\n        return depth;\n    }\n\n    /**\n     * Produce a new layout by splitting a segment at its midpoint.\n     *\n     * @param segmentId the active segment to split\n     * @param nowMs     wall-clock millis used as the parent's seal time and the\n     *                  children's create time. Caller passes a single value so\n     *                  CAS retries and follow-up reads agree.\n     * @return a new SegmentLayout with the split applied\n     */\n    public SegmentLayout splitSegment(long segmentId, long nowMs) {\n        SegmentInfo segment = allSegments.get(segmentId);\n        if (segment == null) {\n            throw new IllegalArgumentException(\"Segment not found: \" + segmentId);\n        }\n        if (!segment.isActive()) {\n            throw new IllegalArgumentException(\"Cannot split non-active segment: \" + segmentId);\n        }\n\n        HashRange[] splitRanges = segment.hashRange().split();\n        long newEpoch = epoch + 1;\n        long childId1 = nextSegmentId;\n        long childId2 = nextSegmentId + 1;\n\n        // PIP-486: a split divides the parent's entry-buckets between its children — N/2 each (at least\n        // 1) — so the topic's total stays ≈ the budget as it fans out into more, narrower segments.\n        List<Integer> childEntryBucketSplits =\n                EntryBucketSplits.equalWidth(Math.max(1, segment.bucketCount() / 2));\n        SegmentInfo sealedParent = segment.sealed(newEpoch, nowMs, List.of(childId1, childId2));\n        SegmentInfo child1 = SegmentInfo.active(childId1, splitRanges[0],\n                List.of(segmentId), newEpoch, nowMs).withEntryBucketSplits(childEntryBucketSplits);\n        SegmentInfo child2 = SegmentInfo.active(childId2, splitRanges[1],","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/scalable/SegmentLayout.java#L150-L186","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlayout.splitSegment(childIdFromOldSnapshot, now);\n// after\nSegmentLayout latest = updated();\nif (latest.allSegments.containsKey(id)) { latest.splitSegment(id, now); }","handlingStrategy":"validation","validationCode":"if (!layout.allSegments.containsKey(segmentId)) {\n    throw new IllegalArgumentException(\"Unknown segmentId \" + segmentId + \"; valid: \" + layout.allSegments.keySet());\n}","typeGuard":"boolean segmentExists(SegmentLayout layout, long segmentId) { return layout.allSegments.get(segmentId) != null; }","tryCatchPattern":"try {\n    layout.splitSegment(id, now);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Split rejected: {} — refresh layout and retry with a valid id\", e.getMessage());\n}","preventionTips":["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"],"tags":["pulsar","scalable-topic","segment-layout","illegal-argument"],"backgroundTag":"segment-not-found","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}