Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Channel hangs on subsequent publish after an AccessRefused error (403) #445

Open
matias-martini opened this issue Jan 8, 2025 · 0 comments

Comments

@matias-martini
Copy link

matias-martini commented Jan 8, 2025

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 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:

from amqp import Connection, Message

# Establish connection and open channel
con = 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

  1. Set up a RabbitMQ user (example-user) with permission to publish on some exchanges, but not on system-configuration.
  2. Run the above code.
  3. Observe that the first publish call fails with AccessRefused (403) as expected.
  4. 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.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant