{"record":{"id":"20c0193b5bcf657d","repo":"apache/pulsar","slug":"no-active-segments","errorCode":null,"errorMessage":"No active segments","messagePattern":"No active segments","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/SegmentRouter.java","lineNumber":55,"sourceCode":"\n    private final AtomicInteger roundRobinCounter = new AtomicInteger(0);\n\n    /**\n     * Route a message key to the segment that owns its hash range.\n     *\n     * <p>If every active segment is a legacy segment (synthetic layout for a not-yet-migrated\n     * regular topic), the routing switches to {@code signSafeMod(murmurHash3_32(key), N)} over\n     * {@code segment_id} so V5 producers route the same way v4 partitioned-topic producers do\n     * — preserving per-key destinations while clients gradually upgrade.\n     *\n     * @param key the message key\n     * @param activeSegments the currently active segments (sorted by hash range)\n     * @return the segment ID to route to\n     * @throws IllegalStateException if no segment covers the hash\n     */\n    long route(String key, List<ActiveSegment> activeSegments) {\n        if (activeSegments.isEmpty()) {\n            throw new IllegalStateException(\"No active segments\");\n        }\n        if (allLegacy(activeSegments)) {\n            return routeModN(key, activeSegments);\n        }\n        int hash = hash(key);\n        for (var segment : activeSegments) {\n            if (segment.hashRange().contains(hash)) {\n                return segment.segmentId();\n            }\n        }\n        throw new IllegalStateException(\"No segment covers hash \" + hash + \" for key: \" + key);\n    }\n\n    /**\n     * Route a message without a key using round-robin across active segments.\n     */\n    long routeRoundRobin(List<ActiveSegment> activeSegments) {\n        if (activeSegments.isEmpty()) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/SegmentRouter.java#L37-L73","documentation":"SegmentRouter.route() throws IllegalStateException when the supplied activeSegments list is empty. The router cannot pick a destination segment without at least one active segment, so routing a keyed message fails fast.","triggerScenarios":"Calling route(key, activeSegments) (directly or through producer routing) with an empty list — e.g. layout not yet loaded, all segments sealed, or a caller passing a filtered/empty list of ActiveSegment.","commonSituations":"Producing immediately after topic creation before the first layout arrives; topic terminated or migrated leaving no active segments; bugs in caller code filtering the segment list to empty.","solutions":["Wait for the initial layout/DAG watch callback before routing; use eagerAttachInitialAsync to pre-populate segments.","Guard the call: check activeSegments non-empty (or fall back to buffering/rejecting sends) before invoking route.","If all segments are sealed, check topic state — the topic may be terminated and should not accept sends.","Fix caller logic that empties the list via filters or stale snapshot handling."],"exampleFix":"// before\nlong seg = router.route(key, activeSegments); // throws when empty\n// after\nif (activeSegments.isEmpty()) { throw new NoLayoutException(\"layout not ready\"); }\nlong seg = router.route(key, activeSegments);","handlingStrategy":"validation","validationCode":"if (activeSegments == null || activeSegments.isEmpty()) {\n    throw new IllegalStateException(\"Layout not ready: no active segments to route key\");\n}\nlong seg = router.route(key, activeSegments);","typeGuard":"static boolean hasActiveSegments(List<SegmentRouter.ActiveSegment> s) {\n    return s != null && !s.isEmpty();\n}","tryCatchPattern":"try {\n    long seg = router.route(key, activeSegments);\n} catch (IllegalStateException e) {\n    // layout not loaded yet: buffer or defer the message\n}","preventionTips":["Wait for the first DAG watch/layout callback before routing","Use eagerAttachInitialAsync to pre-populate active segments","Check topic termination state before producing"],"tags":["routing","segment-layout","illegal-state","pulsar-client"],"backgroundTag":"no-active-segments","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"}