{"record":{"id":"ab0e4216197aaf5e","repo":"micro/go-micro","slug":"could-not-publish-message-received-nack-from-brok","errorCode":null,"errorMessage":"could not publish message, received nack from broker on confirmation","messagePattern":"could not publish message, received nack from broker on confirmation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"broker/rabbitmq/channel.go","lineNumber":91,"sourceCode":"\n\tif r.confirmPublish != nil {\n\t\tr.mtx.Lock()\n\t\tdefer r.mtx.Unlock()\n\t}\n\n\terr := r.channel.Publish(exchange, key, false, false, message)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif r.confirmPublish != nil {\n\t\tconfirmation, ok := <-r.confirmPublish\n\t\tif !ok {\n\t\t\treturn errors.New(\"channel closed before could receive confirmation of publish\")\n\t\t}\n\n\t\tif !confirmation.Ack {\n\t\t\treturn errors.New(\"could not publish message, received nack from broker on confirmation\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (r *rabbitMQChannel) DeclareExchange(ex Exchange) error {\n\treturn r.channel.ExchangeDeclare(\n\t\tex.Name,         // name\n\t\tstring(ex.Type), // kind\n\t\tex.Durable,      // durable\n\t\tfalse,           // autoDelete\n\t\tfalse,           // internal\n\t\tfalse,           // noWait\n\t\tnil,             // args\n\t)\n}\n","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/broker/rabbitmq/channel.go#L73-L109","documentation":"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.","triggerScenarios":"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).","commonSituations":"Publishing to an exchange/queue that was deleted; broker memory/disk alarms causing rejections; transient broker instability under load.","solutions":["Verify the target exchange and queue still exist and bindings are correct.","Retry the publish after checking broker health (alarms, disk/memory).","Re-declare the exchange/queue topology before publishing if topology drift is suspected."],"exampleFix":"// before\nif err := ch.Publish(ex, key, msg); err != nil { return err }\n// after\nif err := ch.Publish(ex, key, msg); err != nil && strings.Contains(err.Error(), \"received nack\") {\n    if derr := declareTopology(ch, ex); derr != nil { return derr }\n    return ch.Publish(ex, key, msg)\n}","handlingStrategy":"try-catch","validationCode":"// verify exchange/queue topology before publishing\nif err := ch.DeclareExchange(ex); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := ch.Publish(ex, key, msg); err != nil {\n    if strings.Contains(err.Error(), \"received nack\") {\n        return fmt.Errorf(\"broker rejected message: %w\", err) // do not blind-retry\n    }\n    return err\n}","preventionTips":["Re-declare exchanges/queues on startup and after reconnects.","Check RabbitMQ alarms (memory/disk) before high-volume publishing.","Alert on nacks instead of auto-retrying, since nacks usually mean topology/broker issues."],"tags":["rabbitmq","amqp","publisher-confirm","nack"],"backgroundTag":"broker-nack-on-publish","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}