nestjs/nest · warning

RMQ broker has blocked the connection (flow control). Reason

Error message

RMQ broker has blocked the connection (flow control). Reason: ${reason}

What it means

The RMQ transport server (ServerRMQ) also publishes: every reply to a requesting client goes back through the broker. When RabbitMQ raises a memory or disk alarm it blocks the server's connection; the BLOCKED listener pushes RmqStatus.BLOCKED into the server's status stream and logs this warning with the broker-supplied reason. While blocked, the server keeps consuming but its replies (sendMessage to replyTo queues) are held back, so RPC callers see rising latency until UNBLOCKED fires.

Source

Thrown at packages/microservices/server/server-rmq.ts:196

  private registerConnectListener() {
    this.server!.on(RmqEventsMap.CONNECT, (err: any) => {
      this._status$.next(RmqStatus.CONNECTED);
    });
  }

  private registerDisconnectListener() {
    this.server!.on(RmqEventsMap.DISCONNECT, (err: any) => {
      this._status$.next(RmqStatus.DISCONNECTED);
      this.logger.error(DISCONNECTED_RMQ_MESSAGE);
      this.logger.error(err);
    });
  }

  private registerBlockedListener() {
    this.server!.on(RmqEventsMap.BLOCKED, ({ reason }: { reason: string }) => {
      this._status$.next(RmqStatus.BLOCKED);
      this.logger.warn(BLOCKED_RMQ_MESSAGE(reason));
    });
  }

  private registerUnblockedListener() {
    this.server!.on(RmqEventsMap.UNBLOCKED, () => {
      this._status$.next(RmqStatus.UNBLOCKED);
      this.logger.log(UNBLOCKED_RMQ_MESSAGE);
    });
  }

  public async setupChannel(channel: Channel, callback: Function) {
    const noAssert =
      this.getOptionsProp(this.options, 'noAssert') ??
      this.queueOptions.noAssert ??
      RMQ_DEFAULT_NO_ASSERT;

    let createdQueue: string;

View on GitHub (pinned to dd75d7bd8c)

Solutions

  1. Resolve the alarm broker-side: `rabbitmqctl status` / `rabbitmq-diagnostics alarms`, free disk, add memory, or raise vm_memory_high_watermark / disk_free_limit with real headroom.
  2. Keep consumer lag bounded (scale handler instances, finite prefetch) so the node stops drifting into alarms.
  3. If you hold the server instance (or via the microservice returned by connectMicroservice), subscribe to its `status` observable to expose BLOCKED/UNBLOCKED in health checks and metrics.
  4. Give RPC callers timeouts so a blocked broker surfaces as errors instead of hangs, and alert on the BLOCKED status.

Example fix

# before: defaults trip alarms early (rabbitmq.conf)
# vm_memory_high_watermark.relative = 0.4
# disk_free_limit.absolute = 50MB

# after: headroom matched to the node/container
vm_memory_high_watermark.relative = 0.6
disk_free_limit.absolute = 2GB
Defensive patterns

Strategy: fallback

Validate before calling

# exit non-zero while any resource alarm is active on the broker
# (alarms are exactly what puts ServerRMQ connections into BLOCKED)
rabbitmqctl eval 'rabbit_alarm:get_alarms().' | grep -q '^\[\]' \
  || echo 'broker alarmed: RMQ connections will be blocked until it clears'

Prevention

When it happens

Trigger: A microservice created with Transport.RMQ whose reply traffic hits a broker resource alarm: connection.blocked with reason 'memory' or 'disk' is emitted on the server's connection. Typically the alarm is caused by queue growth from slow consumers, broker memory pressure, or low disk on the broker node — not necessarily by this service itself.

Common situations: Broker containers with small memory limits under load; a burst of RPC traffic piling up messages (replies and other queues share the node budget); another client on the same node triggering a node-wide alarm that blocks all publishing connections; disk pressure on the broker host.

Related errors


AI-assisted analysis of nestjs/nest@dd75d7bd8c (2026-08-21). Data as JSON: /api/errors/e6ef72dbd94bad91. Report an issue: GitHub.