Files
spring-messaging-demo/rabbitmq/docs/06-changing-your-mind.md
2026-08-29 10:30:21 +05:30

2.5 KiB

← Acknowledgement · Module README

6. Changing your mind about a queue

Queue arguments are immutable. There is no ALTER QUEUE. Redeclaring an existing queue with different arguments is a channel-level error (docs/output/precondition-failed.txt):

PRECONDITION_FAILED - inequivalent arg 'x-message-ttl' for queue 'orders.ttl' in vhost '/':
received '9999' but current is '1500', class-id=50, method-id=10

Reply code 406. The message is precise and helpful, and you will probably never see it, because of what Spring wraps it in:

AmqpIOException: java.io.IOException
  caused by: null
    caused by: channel error; protocol method: #method<channel.close>(reply-code=406, ...)

AmqpIOException's own message is the string java.io.IOException. The next cause's message is null. The useful text is two levels down. This is why the failure gets reported as "some IOException from RabbitMQ" and why it is worth writing a log statement that walks the cause chain.

What this means operationally

Changing a TTL, a max-length, a dead-letter exchange or a queue type on a live queue is not a config edit. It is a migration:

  1. declare the new queue under a new name
  2. bind it alongside the old one
  3. move consumers over
  4. drain the old queue
  5. delete it

Plan the rename into the change from the start — orders.work.v2 is not ugly, it is honest.

A failed declaration stops the ones after it. RabbitAdmin declares beans on connection, and a PRECONDITION_FAILED closes the channel. Declarations queued behind it on that channel do not happen. So one stale queue argument can leave half your topology undeclared, and the symptom is a different queue being missing.

Declarations happen on connection, not on context refresh. A broken topology does not fail startup; it fails the first publish. If you want it to fail at boot, force a connection early — connectionFactory.createConnection() in an ApplicationRunner is enough.

missing-queues-fatal defaults differently for the two container types. It is true for spring.rabbitmq.listener.simple and false for spring.rabbitmq.listener.direct. So the same missing queue kills a simple container and is quietly tolerated by a direct one, which makes "it works in that service" an unhelpful data point. Combined with the point above, a topology error can present as a listener startup problem in one service and as silence in another.

Module README