jsancio commented on code in PR #22111:
URL: https://github.com/apache/kafka/pull/22111#discussion_r3477056199


##########
raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java:
##########
@@ -765,4 +766,122 @@ void testUpdatedHighWatermarkCompleted() throws Exception 
{
             assertEquals(localLogEndOffset, partitionResponse.highWatermark());
         }
     }
+
+    @Test
+    void testObserverFetchesBetweenLeaderAndBootstrapServers() throws 
Exception {
+        final var epoch = 2;
+        final var local = KafkaRaftClientTest.replicaKey(
+            KafkaRaftClientTest.randomReplicaId(),
+            true
+        );
+        final var leader = KafkaRaftClientTest.replicaKey(local.id() + 1, 
true);
+        final var bootstrapVoter = KafkaRaftClientTest.replicaKey(local.id() + 
2, true);
+        final var voters = VoterSet.fromMap(
+            Map.of(
+                leader.id(), VoterSetTest.voterNode(leader),
+                bootstrapVoter.id(), VoterSetTest.voterNode(bootstrapVoter)
+            )
+        );
+
+        final var context = new RaftClientTestContext.Builder(
+            local.id(),
+            local.directoryId().get()
+        )
+            .withStaticVoters(voters)
+            // configure the bootstrap servers to only include the bootstrap 
voter
+            // to reliably check the destination of the observer's fetch 
requests
+            // alternates between the leader and the bootstrap voter
+            .withBootstrapServers(
+                
Optional.of(List.of(RaftClientTestContext.mockAddress(bootstrapVoter.id())))
+            )
+            
.withRaftProtocol(RaftClientTestContext.RaftProtocol.KIP_1166_PROTOCOL)
+            .build();
+
+        // The observer initially fetches from the bootstrap servers,
+        // where it will discover the leader's endpoints.
+        final var bootstrapFetch = pollAndCheckObserverFetchRequest(
+            context,
+            true,
+            bootstrapVoter.id()
+        );
+        context.deliverResponse(
+            bootstrapFetch.correlationId(),
+            bootstrapFetch.destination(),
+            context.fetchResponse(
+                epoch,
+                leader.id(),
+                MemoryRecords.EMPTY,
+                0L,
+                Errors.NOT_LEADER_OR_FOLLOWER
+            )
+        );
+
+        // Subsequent fetch from the observer is sent to the leader
+        // Return a BROKER_NOT_AVAILABLE error, and then advance time past the 
fetch timeout,
+        // which should cause the observer to fetch from the bootstrap servers 
on the next fetch.
+        final var leaderFetch = pollAndCheckObserverFetchRequest(
+            context,
+            false,
+            leader.id()
+        );
+        context.deliverResponse(
+            leaderFetch.correlationId(),
+            leaderFetch.destination(),
+            RaftUtil.errorResponse(
+                ApiKeys.FETCH,
+                Errors.BROKER_NOT_AVAILABLE
+            )
+        );

Review Comment:
   According to the trace I pasted, this response is not deliver before the 
fetch timeout. This is misleading when reading the test.



##########
raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java:
##########
@@ -765,4 +766,122 @@ void testUpdatedHighWatermarkCompleted() throws Exception 
{
             assertEquals(localLogEndOffset, partitionResponse.highWatermark());
         }
     }
+
+    @Test
+    void testObserverFetchesBetweenLeaderAndBootstrapServers() throws 
Exception {
+        final var epoch = 2;
+        final var local = KafkaRaftClientTest.replicaKey(
+            KafkaRaftClientTest.randomReplicaId(),
+            true
+        );
+        final var leader = KafkaRaftClientTest.replicaKey(local.id() + 1, 
true);
+        final var bootstrapVoter = KafkaRaftClientTest.replicaKey(local.id() + 
2, true);
+        final var voters = VoterSet.fromMap(
+            Map.of(
+                leader.id(), VoterSetTest.voterNode(leader),
+                bootstrapVoter.id(), VoterSetTest.voterNode(bootstrapVoter)
+            )
+        );
+
+        final var context = new RaftClientTestContext.Builder(
+            local.id(),
+            local.directoryId().get()
+        )
+            .withStaticVoters(voters)

Review Comment:
   Why use static voters? Why not enable and use all of the latest features?



##########
raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java:
##########
@@ -765,4 +766,122 @@ void testUpdatedHighWatermarkCompleted() throws Exception 
{
             assertEquals(localLogEndOffset, partitionResponse.highWatermark());
         }
     }
+
+    @Test
+    void testObserverFetchesBetweenLeaderAndBootstrapServers() throws 
Exception {
+        final var epoch = 2;
+        final var local = KafkaRaftClientTest.replicaKey(
+            KafkaRaftClientTest.randomReplicaId(),
+            true
+        );
+        final var leader = KafkaRaftClientTest.replicaKey(local.id() + 1, 
true);
+        final var bootstrapVoter = KafkaRaftClientTest.replicaKey(local.id() + 
2, true);
+        final var voters = VoterSet.fromMap(
+            Map.of(
+                leader.id(), VoterSetTest.voterNode(leader),
+                bootstrapVoter.id(), VoterSetTest.voterNode(bootstrapVoter)
+            )
+        );
+
+        final var context = new RaftClientTestContext.Builder(
+            local.id(),
+            local.directoryId().get()
+        )
+            .withStaticVoters(voters)
+            // configure the bootstrap servers to only include the bootstrap 
voter
+            // to reliably check the destination of the observer's fetch 
requests
+            // alternates between the leader and the bootstrap voter
+            .withBootstrapServers(
+                
Optional.of(List.of(RaftClientTestContext.mockAddress(bootstrapVoter.id())))
+            )
+            
.withRaftProtocol(RaftClientTestContext.RaftProtocol.KIP_1166_PROTOCOL)
+            .build();
+
+        // The observer initially fetches from the bootstrap servers,
+        // where it will discover the leader's endpoints.
+        final var bootstrapFetch = pollAndCheckObserverFetchRequest(
+            context,
+            true,
+            bootstrapVoter.id()
+        );
+        context.deliverResponse(
+            bootstrapFetch.correlationId(),
+            bootstrapFetch.destination(),
+            context.fetchResponse(
+                epoch,
+                leader.id(),
+                MemoryRecords.EMPTY,
+                0L,
+                Errors.NOT_LEADER_OR_FOLLOWER
+            )
+        );
+
+        // Subsequent fetch from the observer is sent to the leader
+        // Return a BROKER_NOT_AVAILABLE error, and then advance time past the 
fetch timeout,
+        // which should cause the observer to fetch from the bootstrap servers 
on the next fetch.
+        final var leaderFetch = pollAndCheckObserverFetchRequest(
+            context,
+            false,
+            leader.id()
+        );
+        context.deliverResponse(
+            leaderFetch.correlationId(),
+            leaderFetch.destination(),
+            RaftUtil.errorResponse(
+                ApiKeys.FETCH,
+                Errors.BROKER_NOT_AVAILABLE
+            )
+        );
+
+        // The fetch timeout is much greater than the request manager's 
configured backoff, so the
+        // current unreachable connection will no longer be backing off when 
the next fetch is sent.
+        // Expire the fetch timeout and check that the next fetch is sent to 
the bootstrap server again.
+        context.time.sleep(context.fetchTimeoutMs + 1);

Review Comment:
   I made this changes and the test pass. It looks like the issue is that the 
leader is in the backoff state because kraft got an error from the leader:
   ```bash
   diff --git 
a/raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java 
b/raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java
   index 8d762d6c96..3d873add30 100644
   --- a/raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java
   +++ b/raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java
   @@ -836,7 +836,6 @@ public final class KafkaRaftClientFetchTest {
            // The fetch timeout is much greater than the request manager's 
configured backoff, so the
            // current unreachable connection will no longer be backing off 
when the next fetch is sent.
            // Expire the fetch timeout and check that the next fetch is sent 
to the bootstrap server again.
   -        context.time.sleep(context.fetchTimeoutMs + 1);
            final var nextBootstrapFetch = pollAndCheckObserverFetchRequest(
                context,
                true,
   @@ -854,6 +853,8 @@ public final class KafkaRaftClientFetchTest {
                )
            );
   
   +        context.time.sleep(context.retryBackoffMs);
   +
            // Discovering the leader from a bootstrap fetch means the observer 
resumes fetching from the leader
            pollAndCheckObserverFetchRequest(
                context,
   @@ -871,10 +872,8 @@ public final class KafkaRaftClientFetchTest {
            context.pollUntilRequest();
            RaftRequest.Outbound fetchRequest = 
context.assertSentFetchRequest();
            if (isBootstrapFetch) {
   -            assertTrue(context.client.quorum().isUnattached());
                assertTrue(fetchRequest.destination().id() < -1);
            } else {
   -            assertTrue(context.client.quorum().isFollower());
                assertEquals(expectedDestinationId, 
fetchRequest.destination().id());
            }
            // only need to check port since the host is always "localhost" for 
the mock addresses
   ```



##########
raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java:
##########
@@ -765,4 +766,122 @@ void testUpdatedHighWatermarkCompleted() throws Exception 
{
             assertEquals(localLogEndOffset, partitionResponse.highWatermark());
         }
     }
+
+    @Test
+    void testObserverFetchesBetweenLeaderAndBootstrapServers() throws 
Exception {
+        final var epoch = 2;
+        final var local = KafkaRaftClientTest.replicaKey(
+            KafkaRaftClientTest.randomReplicaId(),
+            true
+        );
+        final var leader = KafkaRaftClientTest.replicaKey(local.id() + 1, 
true);
+        final var bootstrapVoter = KafkaRaftClientTest.replicaKey(local.id() + 
2, true);
+        final var voters = VoterSet.fromMap(
+            Map.of(
+                leader.id(), VoterSetTest.voterNode(leader),
+                bootstrapVoter.id(), VoterSetTest.voterNode(bootstrapVoter)
+            )
+        );
+
+        final var context = new RaftClientTestContext.Builder(
+            local.id(),
+            local.directoryId().get()
+        )
+            .withStaticVoters(voters)
+            // configure the bootstrap servers to only include the bootstrap 
voter
+            // to reliably check the destination of the observer's fetch 
requests
+            // alternates between the leader and the bootstrap voter
+            .withBootstrapServers(
+                
Optional.of(List.of(RaftClientTestContext.mockAddress(bootstrapVoter.id())))
+            )
+            
.withRaftProtocol(RaftClientTestContext.RaftProtocol.KIP_1166_PROTOCOL)
+            .build();
+
+        // The observer initially fetches from the bootstrap servers,
+        // where it will discover the leader's endpoints.
+        final var bootstrapFetch = pollAndCheckObserverFetchRequest(
+            context,
+            true,
+            bootstrapVoter.id()
+        );
+        context.deliverResponse(
+            bootstrapFetch.correlationId(),
+            bootstrapFetch.destination(),
+            context.fetchResponse(
+                epoch,
+                leader.id(),
+                MemoryRecords.EMPTY,
+                0L,
+                Errors.NOT_LEADER_OR_FOLLOWER
+            )
+        );
+
+        // Subsequent fetch from the observer is sent to the leader
+        // Return a BROKER_NOT_AVAILABLE error, and then advance time past the 
fetch timeout,
+        // which should cause the observer to fetch from the bootstrap servers 
on the next fetch.
+        final var leaderFetch = pollAndCheckObserverFetchRequest(
+            context,
+            false,
+            leader.id()
+        );
+        context.deliverResponse(
+            leaderFetch.correlationId(),
+            leaderFetch.destination(),
+            RaftUtil.errorResponse(
+                ApiKeys.FETCH,
+                Errors.BROKER_NOT_AVAILABLE
+            )
+        );
+
+        // The fetch timeout is much greater than the request manager's 
configured backoff, so the
+        // current unreachable connection will no longer be backing off when 
the next fetch is sent.
+        // Expire the fetch timeout and check that the next fetch is sent to 
the bootstrap server again.
+        context.time.sleep(context.fetchTimeoutMs + 1);
+        final var nextBootstrapFetch = pollAndCheckObserverFetchRequest(
+            context,
+            true,
+            bootstrapVoter.id()
+        );
+        context.deliverResponse(
+            nextBootstrapFetch.correlationId(),
+            nextBootstrapFetch.destination(),
+            context.fetchResponse(
+                epoch,
+                leader.id(),
+                MemoryRecords.EMPTY,
+                0L,
+                Errors.NOT_LEADER_OR_FOLLOWER
+            )
+        );
+
+        // Discovering the leader from a bootstrap fetch means the observer 
resumes fetching from the leader
+        pollAndCheckObserverFetchRequest(
+            context,
+            false,
+            leader.id()
+        );
+    }
+
+    //
+    private RaftRequest.Outbound pollAndCheckObserverFetchRequest(
+        RaftClientTestContext context,
+        boolean isBootstrapFetch,
+        int expectedDestinationId
+    ) throws Exception {
+        context.pollUntilRequest();
+        RaftRequest.Outbound fetchRequest = context.assertSentFetchRequest();
+        if (isBootstrapFetch) {
+            assertTrue(context.client.quorum().isUnattached());

Review Comment:
   Let's avoid testing internal kraft state. We should try to test and check 
kraft's externalities: RPCs, writes to the log, etc.



##########
raft/src/test/java/org/apache/kafka/raft/KafkaRaftClientFetchTest.java:
##########
@@ -765,4 +766,122 @@ void testUpdatedHighWatermarkCompleted() throws Exception 
{
             assertEquals(localLogEndOffset, partitionResponse.highWatermark());
         }
     }
+
+    @Test
+    void testObserverFetchesBetweenLeaderAndBootstrapServers() throws 
Exception {

Review Comment:
   I ran this test against this PR and I got this trace:
   ```
   [2026-06-25 15:02:25,329] INFO Starting request manager with bootstrap 
servers: [localhost:10634 (id: -2 rack: null isFenced: false)] 
(org.apache.kafka.raft.KafkaRaftClient:331)
   [2026-06-25 15:02:25,561] INFO Reading KRaft snapshot and log as part of the 
initialization (org.apache.kafka.raft.KafkaRaftClient:509)
   [2026-06-25 15:02:25,563] INFO Starting voters are 
VoterSet(voters={643=VoterNode(voterKey=ReplicaKey(id=643, 
directoryId=<undefined>), 
listeners=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 supportedKRaftVersion=SupportedVersionRange[min_version:0, max_version:0]), 
644=VoterNode(voterKey=ReplicaKey(id=644, directoryId=<undefined>), 
listeners=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10634}),
 supportedKRaftVersion=SupportedVersionRange[min_version:0, max_version:0])}) 
(org.apache.kafka.raft.KafkaRaftClient:511)
   [2026-06-25 15:02:25,565] INFO Attempting durable transition to 
UnattachedState(epoch=0, leaderId=OptionalInt.empty, votedKey=Optional.empty, 
voters=[643, 644], electionTimeoutMs=18985, highWatermark=Optional.empty) from 
null (org.apache.kafka.raft.QuorumState:732)
   [2026-06-25 15:02:25,568] INFO Completed transition to 
UnattachedState(epoch=0, leaderId=OptionalInt.empty, votedKey=Optional.empty, 
voters=[643, 644], electionTimeoutMs=18985, highWatermark=Optional.empty) from 
null (org.apache.kafka.raft.QuorumState:744)
   [2026-06-25 15:02:25,586] TRACE Sent outbound request: 
OutboundRequest(correlationId=0, 
data=FetchRequestData(clusterId='Xs7d_i8LRIuAcKg9hc0dhw', replicaId=-1, 
replicaState=ReplicaState(replicaId=642, replicaEpoch=-1), maxWaitMs=0, 
minBytes=0, maxBytes=1048576, isolationLevel=0, sessionId=0, sessionEpoch=-1, 
topics=[FetchTopic(topic='metadata', topicId=AAAAAAAAAAAAAAAAAAAAAQ, 
partitions=[FetchPartition(partition=0, currentLeaderEpoch=0, fetchOffset=0, 
lastFetchedEpoch=0, logStartOffset=-1, partitionMaxBytes=0, 
replicaDirectoryId=ezHminGtTAmIQQ3i5JFLUQ, highWatermark=-1)])], 
forgottenTopicsData=[], rackId=''), createdTimeMs=1782414145309, 
destination=localhost:10634 (id: -2 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2908)
   [2026-06-25 15:02:25,587] INFO Registered the listener 
org.apache.kafka.raft.RaftClientTestContext$MockListener@107632469 
(org.apache.kafka.raft.KafkaRaftClient:3590)
   [2026-06-25 15:02:25,725] TRACE Received inbound message 
InboundResponse(correlationId=0, data=FetchResponseData(throttleTimeMs=0, 
errorCode=0, sessionId=0, responses=[FetchableTopicResponse(topic='', 
topicId=AAAAAAAAAAAAAAAAAAAAAQ, partitions=[PartitionData(partitionIndex=0, 
errorCode=6, highWatermark=0, lastStableOffset=-1, logStartOffset=-1, 
divergingEpoch=EpochEndOffset(epoch=-1, endOffset=-1), 
currentLeader=LeaderIdAndEpoch(leaderId=643, leaderEpoch=2), 
snapshotId=SnapshotId(endOffset=-1, epoch=-1), abortedTransactions=[], 
preferredReadReplica=-1, records=MemoryRecords(size=0, 
buffer=java.nio.HeapByteBuffer[pos=0 lim=0 cap=37]))])], 
nodeEndpoints=[NodeEndpoint(nodeId=643, host='localhost', port=10633, 
rack=null)]), source=localhost:10634 (id: -2 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2848)
   [2026-06-25 15:02:25,726] INFO Attempting durable transition to 
FollowerState(fetchTimeoutMs=50000, epoch=2, leader=643, 
leaderEndpoints=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 votedKey=Optional.empty, voters=[643, 644], highWatermark=Optional.empty, 
fetchingSnapshot=Optional.empty) from UnattachedState(epoch=0, 
leaderId=OptionalInt.empty, votedKey=Optional.empty, voters=[643, 644], 
electionTimeoutMs=18985, highWatermark=Optional.empty) 
(org.apache.kafka.raft.QuorumState:732)
   [2026-06-25 15:02:25,727] INFO Completed transition to 
FollowerState(fetchTimeoutMs=50000, epoch=2, leader=643, 
leaderEndpoints=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 votedKey=Optional.empty, voters=[643, 644], highWatermark=Optional.empty, 
fetchingSnapshot=Optional.empty) from UnattachedState(epoch=0, 
leaderId=OptionalInt.empty, votedKey=Optional.empty, voters=[643, 644], 
electionTimeoutMs=18985, highWatermark=Optional.empty) 
(org.apache.kafka.raft.QuorumState:744)
   [2026-06-25 15:02:25,728] DEBUG Notifying listener 
org.apache.kafka.raft.RaftClientTestContext$MockListener@107632469 of leader 
change LeaderAndEpoch[leaderId=OptionalInt[643], epoch=2] 
(org.apache.kafka.raft.KafkaRaftClient:4121)
   [2026-06-25 15:02:25,836] TRACE Sent outbound request: 
OutboundRequest(correlationId=1, 
data=FetchRequestData(clusterId='Xs7d_i8LRIuAcKg9hc0dhw', replicaId=-1, 
replicaState=ReplicaState(replicaId=642, replicaEpoch=-1), maxWaitMs=0, 
minBytes=0, maxBytes=1048576, isolationLevel=0, sessionId=0, sessionEpoch=-1, 
topics=[FetchTopic(topic='metadata', topicId=AAAAAAAAAAAAAAAAAAAAAQ, 
partitions=[FetchPartition(partition=0, currentLeaderEpoch=2, fetchOffset=0, 
lastFetchedEpoch=0, logStartOffset=-1, partitionMaxBytes=0, 
replicaDirectoryId=ezHminGtTAmIQQ3i5JFLUQ, highWatermark=-1)])], 
forgottenTopicsData=[], rackId=''), createdTimeMs=1782414145309, 
destination=localhost:10633 (id: 643 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2908)
   [2026-06-25 15:02:25,837] INFO Attempting durable transition to 
UnattachedState(epoch=2, leaderId=OptionalInt[643], votedKey=Optional.empty, 
voters=[643, 644], electionTimeoutMs=9223372036854775807, 
highWatermark=Optional.empty) from FollowerState(fetchTimeoutMs=50000, epoch=2, 
leader=643, 
leaderEndpoints=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 votedKey=Optional.empty, voters=[643, 644], highWatermark=Optional.empty, 
fetchingSnapshot=Optional.empty) (org.apache.kafka.raft.QuorumState:732)
   [2026-06-25 15:02:25,837] INFO Completed transition to 
UnattachedState(epoch=2, leaderId=OptionalInt[643], votedKey=Optional.empty, 
voters=[643, 644], electionTimeoutMs=9223372036854775807, 
highWatermark=Optional.empty) from FollowerState(fetchTimeoutMs=50000, epoch=2, 
leader=643, 
leaderEndpoints=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 votedKey=Optional.empty, voters=[643, 644], highWatermark=Optional.empty, 
fetchingSnapshot=Optional.empty) (org.apache.kafka.raft.QuorumState:744)
   [2026-06-25 15:02:25,837] TRACE Received inbound message 
InboundResponse(correlationId=1, data=FetchResponseData(throttleTimeMs=0, 
errorCode=8, sessionId=0, responses=[], nodeEndpoints=[]), 
source=localhost:10633 (id: 643 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2848)
   [2026-06-25 15:02:25,838] DEBUG Ignoring response 
InboundResponse(correlationId=1, data=FetchResponseData(throttleTimeMs=0, 
errorCode=8, sessionId=0, responses=[], nodeEndpoints=[]), 
source=localhost:10633 (id: 643 rack: null isFenced: false)) since it is no 
longer needed (org.apache.kafka.raft.KafkaRaftClient:2856)
   [2026-06-25 15:02:25,942] TRACE Sent outbound request: 
OutboundRequest(correlationId=2, 
data=FetchRequestData(clusterId='Xs7d_i8LRIuAcKg9hc0dhw', replicaId=-1, 
replicaState=ReplicaState(replicaId=642, replicaEpoch=-1), maxWaitMs=0, 
minBytes=0, maxBytes=1048576, isolationLevel=0, sessionId=0, sessionEpoch=-1, 
topics=[FetchTopic(topic='metadata', topicId=AAAAAAAAAAAAAAAAAAAAAQ, 
partitions=[FetchPartition(partition=0, currentLeaderEpoch=2, fetchOffset=0, 
lastFetchedEpoch=0, logStartOffset=-1, partitionMaxBytes=0, 
replicaDirectoryId=ezHminGtTAmIQQ3i5JFLUQ, highWatermark=-1)])], 
forgottenTopicsData=[], rackId=''), createdTimeMs=1782414195310, 
destination=localhost:10634 (id: -2 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2908)
   [2026-06-25 15:02:25,943] TRACE Received inbound message 
InboundResponse(correlationId=2, data=FetchResponseData(throttleTimeMs=0, 
errorCode=0, sessionId=0, responses=[FetchableTopicResponse(topic='', 
topicId=AAAAAAAAAAAAAAAAAAAAAQ, partitions=[PartitionData(partitionIndex=0, 
errorCode=6, highWatermark=0, lastStableOffset=-1, logStartOffset=-1, 
divergingEpoch=EpochEndOffset(epoch=-1, endOffset=-1), 
currentLeader=LeaderIdAndEpoch(leaderId=643, leaderEpoch=2), 
snapshotId=SnapshotId(endOffset=-1, epoch=-1), abortedTransactions=[], 
preferredReadReplica=-1, records=MemoryRecords(size=0, 
buffer=java.nio.HeapByteBuffer[pos=0 lim=0 cap=37]))])], 
nodeEndpoints=[NodeEndpoint(nodeId=643, host='localhost', port=10633, 
rack=null)]), source=localhost:10634 (id: -2 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2848)
   [2026-06-25 15:02:25,943] INFO Attempting durable transition to 
FollowerState(fetchTimeoutMs=50000, epoch=2, leader=643, 
leaderEndpoints=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 votedKey=Optional.empty, voters=[643, 644], highWatermark=Optional.empty, 
fetchingSnapshot=Optional.empty) from UnattachedState(epoch=2, 
leaderId=OptionalInt[643], votedKey=Optional.empty, voters=[643, 644], 
electionTimeoutMs=9223372036854775807, highWatermark=Optional.empty) 
(org.apache.kafka.raft.QuorumState:732)
   [2026-06-25 15:02:25,944] INFO Completed transition to 
FollowerState(fetchTimeoutMs=50000, epoch=2, leader=643, 
leaderEndpoints=Endpoints(endpoints={ListenerName(LISTENER)=localhost/<unresolved>:10633}),
 votedKey=Optional.empty, voters=[643, 644], highWatermark=Optional.empty, 
fetchingSnapshot=Optional.empty) from UnattachedState(epoch=2, 
leaderId=OptionalInt[643], votedKey=Optional.empty, voters=[643, 644], 
electionTimeoutMs=9223372036854775807, highWatermark=Optional.empty) 
(org.apache.kafka.raft.QuorumState:744)
   [2026-06-25 15:02:26,047] TRACE Sent outbound request: 
OutboundRequest(correlationId=3, 
data=FetchRequestData(clusterId='Xs7d_i8LRIuAcKg9hc0dhw', replicaId=-1, 
replicaState=ReplicaState(replicaId=642, replicaEpoch=-1), maxWaitMs=0, 
minBytes=0, maxBytes=1048576, isolationLevel=0, sessionId=0, sessionEpoch=-1, 
topics=[FetchTopic(topic='metadata', topicId=AAAAAAAAAAAAAAAAAAAAAQ, 
partitions=[FetchPartition(partition=0, currentLeaderEpoch=2, fetchOffset=0, 
lastFetchedEpoch=0, logStartOffset=-1, partitionMaxBytes=0, 
replicaDirectoryId=ezHminGtTAmIQQ3i5JFLUQ, highWatermark=-1)])], 
forgottenTopicsData=[], rackId=''), createdTimeMs=1782414195310, 
destination=localhost:10633 (id: 643 rack: null isFenced: false)) 
(org.apache.kafka.raft.KafkaRaftClient:2908)
   ```
   
   Can we get a TRACE of the actual issue to make sure we are solving the 
correct problem? I am having a hard time understanding the actual problem so I 
am sure that this change solves that problem.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to