acemq_amqp.errors

What this library raises when it will not do something.

Deliberately few. Most of what goes wrong with a broker is the broker's own exception, and wrapping every one of those in a class of ours would hide the detail somebody actually needs while adding a name they then have to learn. These exist for the failures that are ours rather than aio-pika's.

~acemq_amqp.FatalError is not here: it lives with the acknowledgement model in acemq_amqp.ack, because it is a statement about a message rather than about this library.

  1# Copyright 2026 AceMQ.
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#     https://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14
 15"""What this library raises when it will not do something.
 16
 17Deliberately few. Most of what goes wrong with a broker is the broker's own
 18exception, and wrapping every one of those in a class of ours would hide the
 19detail somebody actually needs while adding a name they then have to learn.
 20These exist for the failures that are ours rather than aio-pika's.
 21
 22:class:`~acemq_amqp.FatalError` is not here: it lives with the acknowledgement
 23model in :mod:`acemq_amqp.ack`, because it is a statement about a message rather
 24than about this library.
 25"""
 26
 27from __future__ import annotations
 28
 29
 30class AceMQError(Exception):
 31    """Something this library refused to do."""
 32
 33
 34class SecurityError(AceMQError):
 35    """A security setting that cannot be honoured.
 36
 37    Raised before anything is dialled rather than after: a missing certificate
 38    file, an environment variable that was going to hold the password, or TLS
 39    settings against a URL that is not encrypted are all things to hear about at
 40    start-up. A connection that half-applied them and carried on is the failure
 41    this exists to prevent.
 42    """
 43
 44
 45class PublishError(AceMQError):
 46    """A message the broker would not take, or would not route.
 47
 48    It carries where the message was going, which is the first thing anybody
 49    wants when a routing key was built from a variable.
 50
 51    :param message_id: the envelope identifier it went out with
 52    :param exchange: where it was sent
 53    :param routing_key: what it was sent under
 54    :param reason: the broker's explanation
 55    :param unroutable: true when the message reached no queue rather than being
 56        refused. The broker was working; nothing was listening
 57    :param summary: the whole message, in place of the sentence composed from
 58        the arguments above. For a failure that is about a batch rather than
 59        about one message — :meth:`acemq_amqp.Publisher.send_all` raises one of
 60        these naming how many messages were not confirmed and how many were,
 61        in the words Java and .NET use for the same failure, so that one
 62        runbook covers all of them. A batch failure leaves ``message_id``
 63        empty, because there is no single message it is about
 64    """
 65
 66    def __init__(
 67        self,
 68        message_id: str,
 69        exchange: str,
 70        routing_key: str,
 71        reason: str,
 72        *,
 73        unroutable: bool = False,
 74        summary: str = "",
 75    ) -> None:
 76        self.message_id = message_id
 77        self.exchange = exchange
 78        self.routing_key = routing_key
 79        self.reason = reason
 80        self.unroutable = unroutable
 81
 82        where = f"exchange {exchange!r} with key {routing_key!r}"
 83        if summary:
 84            super().__init__(summary)
 85        elif unroutable:
 86            super().__init__(
 87                f"acemq: message {message_id} to {where} reached no queue: {reason}"
 88            )
 89        else:
 90            super().__init__(f"acemq: cannot publish message {message_id} to {where}: {reason}")
 91
 92
 93class PublishingPausedError(PublishError):
 94    """A publish refused because the broker has blocked this connection.
 95
 96    Declined, not lost. RabbitMQ blocks a connection when it is low on memory
 97    or disk and stops reading the socket until the alarm clears; this library
 98    refuses the publish at once rather than queueing a frame behind a broker
 99    that has said it cannot take it. **Nothing was sent**, so retrying once the
100    broker unblocks cannot duplicate the message — which is what tells this
101    apart from every other :class:`PublishError`, where the message may or may
102    not have arrived.
103
104    A subclass, so an existing ``except PublishError`` still catches it. Catch
105    this one first to back off, shed load or buffer instead of counting a loss.
106    It is Go's ``PublishingPausedError``, .NET's ``ConnectionBlockedException``
107    and the refusal Java's standing load counts as ``refused``.
108
109    ``reason`` is the broker's words when the transport kept them; the RabbitMQ
110    transport cannot (see :attr:`acemq_amqp.Connection.blocked_reason`).
111    """
class AceMQError(builtins.Exception):
31class AceMQError(Exception):
32    """Something this library refused to do."""

Something this library refused to do.

class SecurityError(AceMQError):
35class SecurityError(AceMQError):
36    """A security setting that cannot be honoured.
37
38    Raised before anything is dialled rather than after: a missing certificate
39    file, an environment variable that was going to hold the password, or TLS
40    settings against a URL that is not encrypted are all things to hear about at
41    start-up. A connection that half-applied them and carried on is the failure
42    this exists to prevent.
43    """

A security setting that cannot be honoured.

Raised before anything is dialled rather than after: a missing certificate file, an environment variable that was going to hold the password, or TLS settings against a URL that is not encrypted are all things to hear about at start-up. A connection that half-applied them and carried on is the failure this exists to prevent.

class PublishError(AceMQError):
46class PublishError(AceMQError):
47    """A message the broker would not take, or would not route.
48
49    It carries where the message was going, which is the first thing anybody
50    wants when a routing key was built from a variable.
51
52    :param message_id: the envelope identifier it went out with
53    :param exchange: where it was sent
54    :param routing_key: what it was sent under
55    :param reason: the broker's explanation
56    :param unroutable: true when the message reached no queue rather than being
57        refused. The broker was working; nothing was listening
58    :param summary: the whole message, in place of the sentence composed from
59        the arguments above. For a failure that is about a batch rather than
60        about one message — :meth:`acemq_amqp.Publisher.send_all` raises one of
61        these naming how many messages were not confirmed and how many were,
62        in the words Java and .NET use for the same failure, so that one
63        runbook covers all of them. A batch failure leaves ``message_id``
64        empty, because there is no single message it is about
65    """
66
67    def __init__(
68        self,
69        message_id: str,
70        exchange: str,
71        routing_key: str,
72        reason: str,
73        *,
74        unroutable: bool = False,
75        summary: str = "",
76    ) -> None:
77        self.message_id = message_id
78        self.exchange = exchange
79        self.routing_key = routing_key
80        self.reason = reason
81        self.unroutable = unroutable
82
83        where = f"exchange {exchange!r} with key {routing_key!r}"
84        if summary:
85            super().__init__(summary)
86        elif unroutable:
87            super().__init__(
88                f"acemq: message {message_id} to {where} reached no queue: {reason}"
89            )
90        else:
91            super().__init__(f"acemq: cannot publish message {message_id} to {where}: {reason}")

A message the broker would not take, or would not route.

It carries where the message was going, which is the first thing anybody wants when a routing key was built from a variable.

Parameters
  • message_id: the envelope identifier it went out with
  • exchange: where it was sent
  • routing_key: what it was sent under
  • reason: the broker's explanation
  • unroutable: true when the message reached no queue rather than being refused. The broker was working; nothing was listening
  • summary: the whole message, in place of the sentence composed from the arguments above. For a failure that is about a batch rather than about one message — acemq_amqp.Publisher.send_all() raises one of these naming how many messages were not confirmed and how many were, in the words Java and .NET use for the same failure, so that one runbook covers all of them. A batch failure leaves message_id empty, because there is no single message it is about
PublishError( message_id: str, exchange: str, routing_key: str, reason: str, *, unroutable: bool = False, summary: str = '')
67    def __init__(
68        self,
69        message_id: str,
70        exchange: str,
71        routing_key: str,
72        reason: str,
73        *,
74        unroutable: bool = False,
75        summary: str = "",
76    ) -> None:
77        self.message_id = message_id
78        self.exchange = exchange
79        self.routing_key = routing_key
80        self.reason = reason
81        self.unroutable = unroutable
82
83        where = f"exchange {exchange!r} with key {routing_key!r}"
84        if summary:
85            super().__init__(summary)
86        elif unroutable:
87            super().__init__(
88                f"acemq: message {message_id} to {where} reached no queue: {reason}"
89            )
90        else:
91            super().__init__(f"acemq: cannot publish message {message_id} to {where}: {reason}")
message_id
exchange
routing_key
reason
unroutable
class PublishingPausedError(PublishError):
 94class PublishingPausedError(PublishError):
 95    """A publish refused because the broker has blocked this connection.
 96
 97    Declined, not lost. RabbitMQ blocks a connection when it is low on memory
 98    or disk and stops reading the socket until the alarm clears; this library
 99    refuses the publish at once rather than queueing a frame behind a broker
100    that has said it cannot take it. **Nothing was sent**, so retrying once the
101    broker unblocks cannot duplicate the message — which is what tells this
102    apart from every other :class:`PublishError`, where the message may or may
103    not have arrived.
104
105    A subclass, so an existing ``except PublishError`` still catches it. Catch
106    this one first to back off, shed load or buffer instead of counting a loss.
107    It is Go's ``PublishingPausedError``, .NET's ``ConnectionBlockedException``
108    and the refusal Java's standing load counts as ``refused``.
109
110    ``reason`` is the broker's words when the transport kept them; the RabbitMQ
111    transport cannot (see :attr:`acemq_amqp.Connection.blocked_reason`).
112    """

A publish refused because the broker has blocked this connection.

Declined, not lost. RabbitMQ blocks a connection when it is low on memory or disk and stops reading the socket until the alarm clears; this library refuses the publish at once rather than queueing a frame behind a broker that has said it cannot take it. Nothing was sent, so retrying once the broker unblocks cannot duplicate the message — which is what tells this apart from every other PublishError, where the message may or may not have arrived.

A subclass, so an existing except PublishError still catches it. Catch this one first to back off, shed load or buffer instead of counting a loss. It is Go's PublishingPausedError, .NET's ConnectionBlockedException and the refusal Java's standing load counts as refused.

reason is the broker's words when the transport kept them; the RabbitMQ transport cannot (see acemq_amqp.Connection.blocked_reason).