RabbitMQ Error: Unacked Messages Stuck and Not Redelivered
Fix RabbitMQ messages stuck in unacked state and never redelivered: a consumer holding them without acking. Diagnose prefetch, missing acks, and force redelivery safely.
- #rabbitmq
- #messaging
- #troubleshooting
- #errors
Stuck on this RabbitMQ error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
There is no exception here — the symptom is a queue with messages permanently in the unacked column that never move:
$ rabbitmqctl list_queues name messages messages_ready messages_unacknowledged consumers
Listing queues for vhost / ...
name messages messages_ready messages_unacknowledged consumers
orders 512 0 512 1
Consumers appear connected, messages_ready is 0, but nothing is being processed and the 512 messages_unacknowledged never get redelivered.
What It Means
When a consumer receives a message with manual acknowledgements, RabbitMQ marks it unacknowledged — delivered but not yet confirmed. The broker holds that message and will not give it to another consumer until either the current consumer acks it, nacks/rejects it, or the channel/connection that received it closes. Unacked messages are redelivered only when that delivery context goes away.
So messages “stuck unacked” almost always means a consumer took delivery and then never acked, nacked, or disconnected. The consumer may be deadlocked, blocked on a slow downstream call, or missing an basic.ack in its code path. Because the channel is still open, RabbitMQ correctly refuses to redeliver — from its point of view the messages are still in flight.
Common Causes
- The consumer application has a bug and never calls
basic.ack(or acks the wrong delivery tag). - The consumer is deadlocked or blocked on a slow/hung downstream dependency, holding deliveries indefinitely.
- Prefetch (
basic.qos) is high or unlimited, so one consumer grabbed a large batch it can’t process. - Auto-ack is off but the code assumes messages auto-ack, so acks are never sent.
- A long-running handler exceeds the
consumer_timeoutand the channel is closed by the broker, but a new consumer with the same bug re-holds them. - The consumer keeps the connection open but its processing thread has died.
Diagnostic Commands
See the ready-vs-unacked split and consumer count per queue:
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers --vhost /
Inspect the consumers and their prefetch/ack mode on the queue:
rabbitmqctl list_consumers --vhost / | grep orders
Look at channels to find which one holds unacked messages:
rabbitmqctl list_channels name number messages_unacknowledged prefetch_count
Check the configured consumer timeout (a handler slower than this gets its channel closed):
grep -i consumer_timeout /etc/rabbitmq/rabbitmq.conf
rabbitmqctl eval 'application:get_env(rabbit, consumer_timeout).'
Step-by-Step Resolution
- Confirm the messages really are held by a live consumer, not just sitting ready.
messages_unacknowledged > 0withconsumers >= 1points at a consumer holding them:
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers
- Identify the channel holding the deliveries so you know which client is at fault:
rabbitmqctl list_channels name connection messages_unacknowledged prefetch_count \
| sort -k3 -n | tail
-
Fix the root cause in the consumer: ensure every message path ends in
basic.ack(on success) orbasic.nack/basic.rejectwithrequeue=true(on failure). Never leave a code path that returns without acking. -
Set a sane prefetch so one consumer can’t hoard messages it can’t process:
# pika example
channel.basic_qos(prefetch_count=20)
- To force the stuck messages back into
readyright now, close the delivery context. Requeueing happens automatically when the channel/connection closes — safest is to stop the offending consumer:
# Restart the consumer app, or close its connection by name:
rabbitmqctl close_connection "<connection-name>" "requeue unacked messages"
The unacked messages return to messages_ready and become redeliverable.
- Set/tune
consumer_timeoutso a hung handler is detected and its channel closed automatically instead of holding messages forever:
# /etc/rabbitmq/rabbitmq.conf
consumer_timeout = 1800000 # 30 minutes, in milliseconds
- Confirm the messages redelivered and are draining:
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers
orders 512 0 1
Prevention
- Ack every message exactly once on a definite outcome; make sure no handler path returns without acking or nacking.
- Set a realistic
prefetch_countso consumers don’t grab more than they can process before acking. - Use
basic.nack/basic.rejectwithrequeue=truefor retryable failures so messages move rather than stall. - Keep handlers shorter than
consumer_timeout, or raise the timeout deliberately for legitimately long work. - Add liveness checks so a consumer whose worker thread has died is restarted, releasing its unacked messages.
- Monitor
messages_unacknowledgedper queue and alert when it stays non-zero with no progress.
Related Errors
consumer_timeout/delivery acknowledgement ... timed out— the broker closing a channel whose handler ran too long.PRECONDITION_FAILED - unknown delivery tag— acking a tag that isn’t valid, a common cause of missed acks.basic.nack/ reject-publish overflow — a publisher-side flow issue, not a consumer holding deliveries.channel closedafter a redelivery storm — churn from repeatedly requeued poison messages.
Frequently Asked Questions
Why aren’t my unacked messages being redelivered? Because a consumer still holds them on an open channel; RabbitMQ only redelivers when that consumer acks, nacks, or its channel/connection closes.
How do I force stuck messages back to ready? Close the consumer’s connection or restart the consumer app — unacked messages are automatically requeued when their delivery channel closes.
Does a high prefetch cause this? It makes it worse: a large prefetch_count lets one consumer hold many unacked messages, so set a modest basic.qos value to bound in-flight work.
What is consumer_timeout for? It closes a channel whose handler hasn’t acked within the limit, so a hung consumer releases its messages instead of holding them forever. For a consumer-specific ack strategy, try the DevOps AI prompt library, or browse more RabbitMQ guides.
Fixed it? Get 500 RabbitMQ & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.