You add a dead-letter exchange to the queue declaration in your code, deploy, and the service no longer starts. The channel is closed with:
PRECONDITION_FAILED - inequivalent arg 'x-dead-letter-exchange' for queue 'orders' in vhost 'orders':
received the value 'orders.dlx' of type 'longstr' but current is none
That is the exact message RabbitMQ 4.3.6 returns. Here is what it means and how to get the dead-letter exchange onto the queue without losing a message.
Declaring a queue that already exists is fine as long as the declaration matches: same durability, same arguments. Queue arguments (x- keys in the declare call) are fixed when the queue is created. Your code now declares orders with x-dead-letter-exchange, the queue in the broker was created without it, so RabbitMQ refuses and closes the channel. Nothing changed in the broker; the queue and its messages are untouched.
A passive declare (it only checks that the queue exists) does not compare arguments, which is why a consumer that declares passively keeps working while the publisher that declares fully fails.
Policies can add a dead-letter exchange to an existing queue at runtime. Set one for the queue:
rabbitmqctl set_policy -p orders orders-dlx '^orders$' \
'{"dead-letter-exchange":"orders.dlx"}' --apply-to queues
Then remove x-dead-letter-exchange from the declaration in your code again. What we measured on 4.3.6:
dead-letter-exchange: orders.dlx;requeue=false, arrives in the dead-letter queue: the policy applies to the queue, not only to new messages;Make sure orders.dlx exists and has a queue bound to it before the first message dies. A dead-letter exchange that does not exist is accepted without complaint, and every dead letter is then dropped without an error or a log line (measured: the queue declared with a missing dead-letter exchange, a rejected message gone, the channel still open).
orders.v2) declared with the argument, bound like the old one, consumers moved over, the old queue drained and deleted. More work, but nothing is lost and nothing depends on a policy.Policies have one advantage beyond this error: they live in the broker, so the dead-letter setup of every queue can be changed later without a deploy, and with one pattern for many queues.