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:
- declare the new queue under a new name
- bind it alongside the old one
- move consumers over
- drain the old queue
- delete it
Plan the rename into the change from the start — orders.work.v2 is not ugly, it is honest.
Related failure modes
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.