In what version(s) of Spring for Apache Kafka are you seeing this issue?
4.1.0-M2 and 4.1.0-RC1 (with Spring Boot 4.1.0-M2 / 4.1.0-RC1). Not reproducible on 4.0.x.
Describe the bug
With a non-transactional container and a Kotlin suspend @KafkaListener configured with a DefaultErrorHandler(FixedBackOff(interval, n)), a record whose processing always fails is re-delivered without bound.
A blocking (non-suspend) listener with the identical configuration behaves as expected: it is delivered n + 1 times (initial delivery + n retries) and then stops.
For the suspend listener, the delivery count keeps growing indefinitely. With a DeadLetterPublishingRecoverer, a new DLT copy is published on every cycle.
To Reproduce
Minimal project: https://github.com/lobodpav/spring-kafka-retry-issue. No transactions, no @RetryableTopic, no custom recoverer — just Spring Boot + spring-kafka + a Testcontainers broker, with one blocking and one suspend @KafkaListener that always throw, and a DefaultErrorHandler(FixedBackOff(100L, 2L)).
Run ./gradlew test. One record is sent to each topic; the test asserts each listener is delivered 3 times. The blocking assertion passes; the suspend assertion fails because suspendDeliveries keeps growing.
Expected behavior
The suspend/async listener should behave like the blocking one: it is delivered n + 1 times and then stops; the record is not re-delivered after retries are exhausted.
Actual behavior
The record is re-delivered forever.
With FixedBackOff(100L, 2L) (initial delivery + 2 retries → expected 3 deliveries), and one record sent to each topic:
blockingDeliveries settles at 3 and stops.
suspendDeliveries keeps climbing (≈18–20 within 10s at a 100 ms back off) and never settles.
Sample
https://github.com/lobodpav/spring-kafka-retry-issue
In what version(s) of Spring for Apache Kafka are you seeing this issue?
4.1.0-M2and4.1.0-RC1(with Spring Boot4.1.0-M2/4.1.0-RC1). Not reproducible on4.0.x.Describe the bug
With a non-transactional container and a Kotlin
suspend@KafkaListenerconfigured with aDefaultErrorHandler(FixedBackOff(interval, n)), a record whose processing always fails is re-delivered without bound.A blocking (non-suspend) listener with the identical configuration behaves as expected: it is delivered
n + 1times (initial delivery +nretries) and then stops.For the
suspendlistener, the delivery count keeps growing indefinitely. With aDeadLetterPublishingRecoverer, a new DLT copy is published on every cycle.To Reproduce
Minimal project: https://github.com/lobodpav/spring-kafka-retry-issue. No transactions, no
@RetryableTopic, no custom recoverer — just Spring Boot + spring-kafka + a Testcontainers broker, with one blocking and onesuspend@KafkaListenerthat always throw, and aDefaultErrorHandler(FixedBackOff(100L, 2L)).Run
./gradlew test. One record is sent to each topic; the test asserts each listener is delivered 3 times. The blocking assertion passes; thesuspendassertion fails becausesuspendDeliverieskeeps growing.Expected behavior
The
suspend/async listener should behave like the blocking one: it is deliveredn + 1times and then stops; the record is not re-delivered after retries are exhausted.Actual behavior
The record is re-delivered forever.
With
FixedBackOff(100L, 2L)(initial delivery + 2 retries → expected 3 deliveries), and one record sent to each topic:blockingDeliveriessettles at 3 and stops.suspendDeliverieskeeps climbing (≈18–20 within 10s at a 100 ms back off) and never settles.Sample
https://github.com/lobodpav/spring-kafka-retry-issue