{"record":{"id":"a98611794108cbe0","repo":"apache/druid","slug":"cannot-allocate-segment-if-not-leader","errorCode":null,"errorMessage":"Cannot allocate segment if not leader.","messagePattern":"Cannot allocate segment if not leader\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/actions/SegmentAllocationQueue.java","lineNumber":217,"sourceCode":"    }\n  }\n\n  /**\n   * Gets the number of batches currently in the queue.\n   */\n  public int size()\n  {\n    return processingQueue.size();\n  }\n\n  /**\n   * Queues a SegmentAllocateRequest. The returned future may complete successfully\n   * with a non-null value or with a non-null value.\n   */\n  public Future<SegmentIdWithShardSpec> add(SegmentAllocateRequest request)\n  {\n    if (!isLeader.get()) {\n      throw new ISE(\"Cannot allocate segment if not leader.\");\n    } else if (!isEnabled()) {\n      throw new ISE(\"Batched segment allocation is disabled.\");\n    }\n\n    final AllocateRequestKey requestKey = new AllocateRequestKey(request);\n    final AtomicReference<Future<SegmentIdWithShardSpec>> futureReference = new AtomicReference<>();\n\n    // Possible race condition:\n    // t1 -> new batch is added to queue or batch already exists in queue\n    // t2 -> executor pops batch, processes all requests in it\n    // t1 -> new request is added to dangling batch and is never picked up\n    // Solution: Perform the following operations only inside keyToBatch.compute():\n    // 1. Add or remove from map\n    // 2. Add batch to queue\n    // 3. Mark batch as started\n    // 4. Update requests in batch\n    keyToBatch.compute(requestKey, (key, existingBatch) -> {\n      if (existingBatch == null || existingBatch.isStarted() || existingBatch.isFull()) {","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/actions/SegmentAllocationQueue.java#L199-L235","documentation":"SegmentAllocationQueue.add() is the entry point that queues a segment-allocation request for batched processing, but only the Overlord leader may process allocations. When the local isLeader flag is false, the node rejects the request with this ISE instead of queueing work it cannot complete. It protects against followers/duplicates accepting allocation duties.","triggerScenarios":"Calling add() on a SegmentAllocationQueue hosted on a non-leader Overlord, or during a leadership transition where the isLeader AtomicBoolean has been flipped off (leader lost leadership) while tasks still route requests to this node.","commonSituations":"Middle managers/tasks hitting a standby Overlord due to stale service discovery; Overlord leadership failover mid-ingestion; split-horizon deployments where task routing points at the wrong Overlord.","solutions":["Verify tasks/actions are routed to the current Overlord leader (check druid.overlord.leaderSelector / coordinator console).","Wait for or trigger Overlord leader election to complete, then retry the allocation (tasks retry automatically).","Fix load-balancer or service-discovery config so standby Overlords do not receive task-action traffic.","Check for ZooKeeper/leadership flapping in the cluster logs and stabilize the Overlord group."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before issuing SEGMENT_ALLOCATE, confirm this Overlord is leader:\n// GET /druid/indexer/v1/leader -> compare with the Overlord being called","typeGuard":null,"tryCatchPattern":"try { future = queue.add(request); } catch (ISE e) { if (e.getMessage().contains(\"not leader\")) { /* re-route to leader Overlord or wait for election and retry */ } else throw e; }","preventionTips":["Route task actions only to the current Overlord leader.","Fix load balancer/service discovery to exclude standby Overlords.","Watch for leadership flapping in Overlord logs.","Retry task actions on leader-change exceptions."],"tags":["druid","overlord","leader-election","segment-allocation"],"backgroundTag":"not-leader-node","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}