In what version(s) of Spring AMQP are you seeing this issue?
main
Describe the bug
org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainerTests#testAddQueuesAndStartInCycle
can fail with a ConcurrentModificationException
on shutdown. It doesn't happen every time so either the test needs to be more robust or it exposes an actual issue in SimpleMessageListenerContainer
:
2025-08-22 08:22:24,015 INFO org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer [main] : Waiting for workers to finish.
2025-08-22 08:22:24,016 INFO org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer [main] : Workers not finished.
2025-08-22 08:22:24,016 ERROR org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer [not.a.Spring.bean-3] : Stopping container from aborted consumer
org.springframework.amqp.UncategorizedAmqpException: java.util.ConcurrentModificationException
at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:81)
at org.springframework.amqp.rabbit.connection.RabbitAccessor.convertRabbitAccessException(RabbitAccessor.java:117)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.shutdown(AbstractMessageListenerContainer.java:1345)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.shutdown(AbstractMessageListenerContainer.java:1313)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doStop(AbstractMessageListenerContainer.java:1468)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.stop(AbstractMessageListenerContainer.java:1454)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainerTests.testAddQueuesAndStartInCycle(SimpleMessageListenerContainerTests.java:417)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:186)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:215)
at java.base/java.util.stream.IntPipeline$1$1.accept(IntPipeline.java:180)
at java.base/java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:104)
at java.base/java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:712)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:153)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:176)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:636)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
Caused by: java.util.ConcurrentModificationException
at java.base/java.util.ArrayList.forEach(ArrayList.java:1606)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.lambda$shutdownAndWaitOrCallback$0(SimpleMessageListenerContainer.java:709)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.shutdownAndWaitOrCallback(SimpleMessageListenerContainer.java:736)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.shutdown(AbstractMessageListenerContainer.java:1342)
... 19 more
To Reproduce
Replace @Test
by @RepeatedTest(100)
and it should eventually fail.
Comment From: snicoll
this.processorThreadsToInterrupt
can be updated whiile shutdownAndWaitOrCallback
is looping over it. I suppose there are other areas, in particular in Spring Framework, where this happens and there's an idiomatic way of dealing with that problem.
Comment From: artembilan
Thank you, Stephane! This is new: have just pushed that new functionality yesterday . I think I know what is going on: while we are looping in the mention method, one of the processors might finish normally removing itself from that list. Just synchronization on the list should be enough to fix.
Will look into that when I’m back.
Comment From: artembilan
Regression after: https://github.com/spring-projects/spring-amqp/issues/2920