{"record":{"id":"f0c7669d246b9bdf","repo":"provectus/kafka-ui","slug":"topic-partition-s-has-no-leader","errorCode":null,"errorMessage":"Topic partition %s has no leader","messagePattern":"Topic partition (.+?) has no leader","errorType":"validation","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/ReactiveAdminClient.java","lineNumber":581,"sourceCode":"    var targetTopics = partitions.stream().map(TopicPartition::topic).collect(Collectors.toSet());\n    return describeTopicsImpl(targetTopics)\n        .map(descriptions ->\n            filterPartitionsWithLeaderCheck(\n                descriptions.values(), partitions::contains, failOnUnknownLeader));\n  }\n\n  @VisibleForTesting\n  static Set<TopicPartition> filterPartitionsWithLeaderCheck(Collection<TopicDescription> topicDescriptions,\n                                                              Predicate<TopicPartition> partitionPredicate,\n                                                              boolean failOnUnknownLeader) {\n    var goodPartitions = new HashSet<TopicPartition>();\n    for (TopicDescription description : topicDescriptions) {\n      var goodTopicPartitions = new ArrayList<TopicPartition>();\n      for (TopicPartitionInfo partitionInfo : description.partitions()) {\n        TopicPartition topicPartition = new TopicPartition(description.name(), partitionInfo.partition());\n        if (partitionInfo.leader() == null) {\n          if (failOnUnknownLeader) {\n            throw new ValidationException(String.format(\"Topic partition %s has no leader\", topicPartition));\n          } else {\n            // if ANY of topic partitions has no leader - we have to skip all topic partitions\n            goodTopicPartitions.clear();\n            break;\n          }\n        }\n        if (partitionPredicate.test(topicPartition)) {\n          goodTopicPartitions.add(topicPartition);\n        }\n      }\n      goodPartitions.addAll(goodTopicPartitions);\n    }\n    return goodPartitions;\n  }\n\n  // 1. NOTE(!): should only apply for partitions from topics where all partitions have leaders,\n  //    otherwise AdminClient will try to fetch topic metadata, fail and retry infinitely (until timeout)\n  // 2. NOTE(!): Skips partitions that were not initialized yet","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/provectus/kafka-ui/blob/83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/ReactiveAdminClient.java#L563-L599","documentation":"ReactiveAdminClient.filterPartitionsWithLeaderCheck inspects TopicDescription metadata and throws ValidationException when a partition has no leader broker. Without a leader, offset lookups cannot be served for that partition, so operations like listOffsets would fail; when failOnUnknownLeader is true the client fails fast instead of returning incomplete data. When false, partitions of that topic are silently skipped rather than throwing.","triggerScenarios":"Calling listTopicOffsets/listOffsets (e.g., GET topic offsets, consumer-group lag calculations) while one or more partitions of the topic have no leader — typically during or right after a broker failure, partition reassignment, or unclean leader election where the metadata still reports leader == null.","commonSituations":"A broker crashed and the cluster has not finished leader election; replication factor 1 and the only replica (leader) host is down; under-replicated/offline partitions after maintenance or rolling restart; topic reassignment in progress so the partition temporarily has no leader.","solutions":["Restore broker availability: restart/recover the down broker(s) so a leader is elected for the affected partitions.","Increase the topic's replication factor (>= 2) so leader election can occur when one replica is down.","Retry the offset listing after the controller finishes leader election (the condition is usually transient).","Check `kafka-topics --describe --under-replicated-partitions` / `--unavailable-partitions` and fix the offline partitions.","If using the code path directly, set failOnUnknownLeader=false to skip leaderless topics instead of throwing."],"exampleFix":"// before: fail immediately on leaderless partitions\nListOffsetsResult result = adminClient.listOffsets(offsetsToFetch);\n// after: tolerate/skip leaderless partitions\n// (in listOffsets call chain) use failOnUnknownLeader=false so\n// filterPartitionsWithLeaderCheck skips topics with leaderless partitions\nMap<TopicPartition, OffsetSpec> fetchable = filterPartitionsWithLeaderCheck(\n    adminClient.describeTopics(names).allTopicNames().get(), fetch, false);","handlingStrategy":"retry","validationCode":"const desc = await fetch(`/api/clusters/${cluster}/topics/${topic}`).then(r => r.json());\nif (desc.partitions.some(p => p.leader == null)) {\n  console.warn(`Topic ${topic} has leaderless partitions; defer offset listing`);\n}","typeGuard":"function hasLeaders(topicDesc) {\n  return topicDesc.partitions.every(p => p.leader != null);\n}","tryCatchPattern":"try {\n  offsets = await listTopicOffsets(cluster, topic);\n} catch (e) {\n  if (e.message.includes('has no leader')) {\n    await sleep(backoff); // leader election is usually transient\n    offsets = await listTopicOffsets(cluster, topic);\n  } else { throw e; }\n}","preventionTips":["Monitor under-replicated and offline partitions; alert before consumers lag calculations run.","Use replication factor >= 2 for topics whose offsets you read programmatically.","Add retry with backoff around offset/lag operations during rolling broker maintenance."],"tags":["kafka","topic-partitions","leader-election","cluster-health"],"backgroundTag":"resource-not-found","analyzedSha":"83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7","analyzedAt":"2026-09-08T04:35:39.002Z","contentChangedAt":"2026-09-08T04:35:39.002Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}