knadh/listmonk · error

unknown messenger %s on campaign %s

Error message

unknown messenger %s on campaign %s

What it means

newPipe validates that the campaign's Messenger field names a messenger registered with the manager. If it doesn't, the campaign is immediately marked cancelled in the store and this error is returned, so the campaign will never send with an unknown backend.

Source

Thrown at internal/manager/pipe.go:31

type pipe struct {
	camp       *models.Campaign
	rate       *ratecounter.RateCounter
	wg         *sync.WaitGroup
	sent       atomic.Int64
	lastID     atomic.Uint64
	errors     atomic.Uint64
	stopped    atomic.Bool
	withErrors atomic.Bool

	m *Manager
}

// newPipe adds a campaign to the process queue.
func (m *Manager) newPipe(c *models.Campaign) (*pipe, error) {
	// Validate messenger.
	if _, ok := m.messengers[c.Messenger]; !ok {
		m.store.UpdateCampaignStatus(c.ID, models.CampaignStatusCancelled)
		return nil, fmt.Errorf("unknown messenger %s on campaign %s", c.Messenger, c.Name)
	}

	// Resolve any inline images before compiling the template.
	if err := m.LoadInlineImages(c); err != nil {
		return nil, err
	}

	// Load the template.
	if err := c.CompileTemplate(m.TemplateFuncs(c)); err != nil {
		return nil, err
	}

	// Load any media/attachments.
	if err := m.attachMedia(c); err != nil {
		return nil, err
	}

	// Add the campaign to the active map.

View on GitHub (pinned to 670c01717d)

Solutions

  1. Register the missing messenger in configuration so AddMessenger is called for the name the campaign uses
  2. Update the campaign's messenger field to an installed/registered messenger name
  3. Check campaign Messenger value against the names returned by each messenger's Name() (case-sensitive match)
  4. Note the campaign was auto-cancelled — after fixing config, reset the campaign status to draft/running to resend

Example fix

// before
messenger = "mailgun" // mailgun not configured on this instance
// after
messenger = "smtp" // registered provider, matches msg.Name()
Defensive patterns

Strategy: validation

Validate before calling

// Before setting a campaign live, confirm the messenger is registered
if !mgr.HasMessenger(campaign.Messenger) {
    return fmt.Errorf("messenger %q is not configured on this instance", campaign.Messenger)
}

Try / catch

if _, err := m.newPipe(c); err != nil {
    if strings.Contains(err.Error(), "unknown messenger") {
        // campaign was auto-cancelled; fix config, reset status, requeue
        return fixMessengerAndRequeue(c)
    }
    return err
}

Prevention

When it happens

Trigger: scanCampaigns picks up a 'running' campaign whose messenger value doesn't match any registered messenger name — e.g. campaign configured for a messenger/provider that isn't initialized (disabled in config, provider not added via AddMessenger, or renamed).

Common situations: Config disabling a messenger (e.g. SMTP) while campaigns still target it, renaming a messenger and leaving old campaigns pointing at the old name, database imported from another instance with different messenger names, or initCaptcha-style provider init failing silently so the messenger was never registered.

Related errors


AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01). Data as JSON: /api/errors/44d8276f5675a68a. Report an issue: GitHub.