You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When attempting to publish a message to an exchange that the user does not have permission to write to, the channel raises an AccessRefused error (403) as expected. However, after this error occurs, subsequent attempts to publish on the same channel hang indefinitely instead of returning an error or otherwise recovering gracefully.
According to the AMQP 0-9-1 protocol, when a 403 (“AccessRefused”) is triggered, the broker typically sends a channel.close method. The client library should then close that channel and raise an exception, allowing the user to handle the error and open a new channel if needed. In some cases, RabbitMQ may also set certain flags (e.g., connection.blocked frames or channel-blocked signals) depending on how the broker is configured and how the error is propagated.
In this scenario, it appears that py-amqp either does not fully close or reset the channel after receiving the AccessRefused, leaving the channel in a “blocked” or “bad” state. Any subsequent publish calls on this channel remain stuck because the broker has effectively closed or blocked the channel from further use.
Below is a minimal reproducible example demonstrating the issue:
fromamqpimportConnection, Message# Establish connection and open channelcon=Connection(host='rabbitmq', userid='example-user', password='example-user', virtual_host='/')
con.connect()
chan=con.channel()
# 1) This line triggers an AccessRefused exception because the user lacks permission:# AccessRefused: Basic.publish: (403) ACCESS_REFUSED - write access to exchange 'system-configuration'# in vhost '/' refused for user 'example-user'chan.basic_publish_confirm(Message(b''), 'system-configuration', 'a.config.c')
# 2) After the above error occurs, attempting to reuse the same channel hangs forever:chan.basic_publish_confirm(Message(b''), 'example-exchange', 'a.config.c')
Steps to Reproduce
Set up a RabbitMQ user (example-user) with permission to publish on some exchanges, but not on system-configuration.
Run the above code.
Observe that the first publish call fails with AccessRefused (403) as expected.
Note that the second publish call never returns, causing the application to hang indefinitely.
Expected Behavior
After encountering AccessRefused, the channel should close or become invalid, and the library should raise a clear exception if further operations are attempted.
Future calls on the same channel should either fail fast with an error indicating the channel is closed, or allow the application to recover by reopening or recreating the channel.
Actual Behavior
The channel appears to enter a “blocked” or otherwise bad state after the first failed publish.
Subsequent calls to basic_publish_confirm with valid exchanges hang and never return.
The library does not appear to handle the channel close gracefully.
Environment
py-amqp version: 5.3.1
Python version: 3.13
RabbitMQ version: 3.13
OS: Debian 12.5-slim (based on python:3.13-slim Docker image)
Additional Notes
This behavior suggests that py-amqp is not handling the server’s channel.close (or related block signals) properly in response to the 403 error.
A workaround is to catch the AccessRefused exception explicitly, discard the failed channel, and open a new one for subsequent operations. However, the more intuitive behavior would be for py-amqp to automatically detect the channel is closed and raise an error on further usage, rather than hanging.
Please let me know if any additional logs or information would help diagnose this issue further.
The text was updated successfully, but these errors were encountered:
Description
When attempting to publish a message to an exchange that the user does not have permission to write to, the channel raises an
AccessRefused
error (403) as expected. However, after this error occurs, subsequent attempts to publish on the same channel hang indefinitely instead of returning an error or otherwise recovering gracefully.According to the AMQP 0-9-1 protocol, when a
403
(“AccessRefused”) is triggered, the broker typically sends achannel.close
method. The client library should then close that channel and raise an exception, allowing the user to handle the error and open a new channel if needed. In some cases, RabbitMQ may also set certain flags (e.g.,connection.blocked
frames or channel-blocked signals) depending on how the broker is configured and how the error is propagated.In this scenario, it appears that py-amqp either does not fully close or reset the channel after receiving the
AccessRefused
, leaving the channel in a “blocked” or “bad” state. Any subsequent publish calls on this channel remain stuck because the broker has effectively closed or blocked the channel from further use.Below is a minimal reproducible example demonstrating the issue:
Steps to Reproduce
example-user
) with permission to publish on some exchanges, but not onsystem-configuration
.AccessRefused (403)
as expected.Expected Behavior
AccessRefused
, the channel should close or become invalid, and the library should raise a clear exception if further operations are attempted.Actual Behavior
basic_publish_confirm
with valid exchanges hang and never return.Environment
python:3.13-slim
Docker image)Additional Notes
channel.close
(or related block signals) properly in response to the403
error.AccessRefused
exception explicitly, discard the failed channel, and open a new one for subsequent operations. However, the more intuitive behavior would be for py-amqp to automatically detect the channel is closed and raise an error on further usage, rather than hanging.The text was updated successfully, but these errors were encountered: