micro/go-micro · error

could not publish message, received nack from broker on conf

Error message

could not publish message, received nack from broker on confirmation

What it means

With publisher confirms enabled, after receiving a confirmation Publish checks confirmation.Ack. If the broker sent a nack, the message was rejected/not persisted by RabbitMQ, and this error is returned. Unlike the closed-channel case, the broker explicitly said the message was not accepted.

Source

Thrown at broker/rabbitmq/channel.go:91

	if r.confirmPublish != nil {
		r.mtx.Lock()
		defer r.mtx.Unlock()
	}

	err := r.channel.Publish(exchange, key, false, false, message)
	if err != nil {
		return err
	}

	if r.confirmPublish != nil {
		confirmation, ok := <-r.confirmPublish
		if !ok {
			return errors.New("channel closed before could receive confirmation of publish")
		}

		if !confirmation.Ack {
			return errors.New("could not publish message, received nack from broker on confirmation")
		}
	}

	return nil
}

func (r *rabbitMQChannel) DeclareExchange(ex Exchange) error {
	return r.channel.ExchangeDeclare(
		ex.Name,         // name
		string(ex.Type), // kind
		ex.Durable,      // durable
		false,           // autoDelete
		false,           // internal
		false,           // noWait
		nil,             // args
	)
}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Verify the target exchange and queue still exist and bindings are correct.
  2. Retry the publish after checking broker health (alarms, disk/memory).
  3. Re-declare the exchange/queue topology before publishing if topology drift is suspected.

Example fix

// before
if err := ch.Publish(ex, key, msg); err != nil { return err }
// after
if err := ch.Publish(ex, key, msg); err != nil && strings.Contains(err.Error(), "received nack") {
    if derr := declareTopology(ch, ex); derr != nil { return derr }
    return ch.Publish(ex, key, msg)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify exchange/queue topology before publishing
if err := ch.DeclareExchange(ex); err != nil { return err }

Try / catch

if err := ch.Publish(ex, key, msg); err != nil {
    if strings.Contains(err.Error(), "received nack") {
        return fmt.Errorf("broker rejected message: %w", err) // do not blind-retry
    }
    return err
}

Prevention

When it happens

Trigger: RabbitMQ nacks a confirm-mode publish — typically when the broker cannot route/persist the message (queue gone at publish time, internal broker error, mandatory/unroutable scenarios).

Common situations: Publishing to an exchange/queue that was deleted; broker memory/disk alarms causing rejections; transient broker instability under load.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/ab0e4216197aaf5e. Report an issue: GitHub.