nsqio/nsq · warning

E_MPUB_FAILED

E_MPUB_FAILED

Error message

exiting

What it means

Topic.PutMessages (nsqd/topic.go) is the batched write path used by the MPUB and MPUB cl commands. Like PutMessage it refuses work when the topic's exitFlag is set (topic deleting or nsqd shutting down) and returns 'exiting'; the protocol layer maps that to E_MPUB_FAILED for the client. If a later message in the loop fails, only the successfully written prefix is credited to messageCount/messageBytes — the guard and the accounting both exist because MPUB is not transactional.

Source

Thrown at nsqd/topic.go:203

	defer t.RUnlock()
	if atomic.LoadInt32(&t.exitFlag) == 1 {
		return errors.New("exiting")
	}
	err := t.put(m)
	if err != nil {
		return err
	}
	atomic.AddUint64(&t.messageCount, 1)
	atomic.AddUint64(&t.messageBytes, uint64(len(m.Body)))
	return nil
}

// PutMessages writes multiple Messages to the queue
func (t *Topic) PutMessages(msgs []*Message) error {
	t.RLock()
	defer t.RUnlock()
	if atomic.LoadInt32(&t.exitFlag) == 1 {
		return errors.New("exiting")
	}

	messageTotalBytes := 0

	for i, m := range msgs {
		err := t.put(m)
		if err != nil {
			atomic.AddUint64(&t.messageCount, uint64(i))
			atomic.AddUint64(&t.messageBytes, uint64(messageTotalBytes))
			return err
		}
		messageTotalBytes += len(m.Body)
	}

	atomic.AddUint64(&t.messageBytes, uint64(messageTotalBytes))
	atomic.AddUint64(&t.messageCount, uint64(len(msgs)))
	return nil
}

View on GitHub (pinned to 85cf10c09c)

Solutions

  1. Retry the batch after the producer reconnects and the topic exists again (go-nsq Producer.Publish of multiple messages / MPUB handles reconnect internally).
  2. For ephemeral topics, keep at least one non-ephemeral channel so the topic is not deleted under your producer.
  3. Drain or stop producers before deleting topics or stopping nsqd when you need the last batches accepted.
  4. Treat E_MPUB_FAILED as non-permanent for this condition: log, back off briefly, re-resolve the topic, resend.

Example fix

# before: fire-and-forget MPUB during restarts
$ nsq_pub -topic alerts -multimsg msgs.txt  # may fail with E_MPUB_FAILED (exiting)

# after: retry once after reconnect/re-resolve
for i in 1 2; do
  nsq_pub -topic alerts -multimsg msgs.txt && break
  sleep 1   # let nsqd restart / topic recreate, then retry the whole batch
  nsq_pub -topic alerts -create-topic >/dev/null
  done
Defensive patterns

Strategy: retry

Validate before calling

// with go-nsq, verify the producer is connected and the topic exists before MPUB
if p := nsqProducer; !p.Ping() {
    // go-nsq reconnects internally; wait or fail fast before batching
    return errors.New("producer not connected; deferring MPUB")
}

Try / catch

// treat E_MPUB_FAILED / exiting as transient: back off and resend the batch
if err := producer.MultiPublish(msgs); err != nil {
    if strings.Contains(err.Error(), "E_MPUB_FAILED") || strings.Contains(err.Error(), "exiting") {
        time.Sleep(backoff)
        err = producer.MultiPublish(msgs) // idempotent consumers recommended
    }
    return err
}

Prevention

When it happens

Trigger: An MPUB (or internal PutMessages) racing topic deletion or nsqd shutdown: exitFlag is observed as 1 before any message is written and the whole batch is rejected with E_MPUB_FAILED. Also triggered when batch writes straddle shutdown: some messages land, then the error surfaces after the partial counters are updated.

Common situations: Consumers using ephemeral topics that auto-delete when their channels drain while a producer MPUBs; deployment scripts killing nsqd before producers drain; burst publishing during rolling restarts; test harnesses tearing down nsqd immediately after publishing.

Related errors


AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16). Data as JSON: /api/errors/c726fb3bd343e588. Report an issue: GitHub.