{"record":{"id":"f88f4cac04c2b0a1","repo":"knadh/listmonk","slug":"campaigns-fieldinvalidmessenger","errorCode":null,"errorMessage":"campaigns.fieldInvalidMessenger","messagePattern":"campaigns\\.fieldInvalidMessenger","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/campaigns.go","lineNumber":727,"sourceCode":"\t}\n\n\t// If there's a \"send_at\" date, it should be in the future.\n\tif c.SendAt.Valid {\n\t\tif c.SendAt.Time.Before(time.Now()) {\n\t\t\treturn c, errors.New(a.i18n.T(\"campaigns.fieldInvalidSendAt\"))\n\t\t}\n\t}\n\n\tif len(c.ListIDs) == 0 {\n\t\treturn c, errors.New(a.i18n.T(\"campaigns.fieldInvalidListIDs\"))\n\t}\n\n\tif !a.manager.HasMessenger(c.Messenger) {\n\t\t// If it's a specific SMTP, but it's no longer available (removed/disabled), fall back to general email messenger.\n\t\tif strings.HasPrefix(c.Messenger, \"email-\") {\n\t\t\tc.Messenger = \"email\"\n\t\t} else {\n\t\t\treturn c, errors.New(a.i18n.Ts(\"campaigns.fieldInvalidMessenger\", \"name\", c.Messenger))\n\t\t}\n\t}\n\n\tcamp := models.Campaign{Body: c.Body, TemplateBody: tplTag}\n\tif err := c.CompileTemplate(a.manager.TemplateFuncs(&camp)); err != nil {\n\t\treturn c, errors.New(a.i18n.Ts(\"campaigns.fieldInvalidBody\", \"error\", err.Error()))\n\t}\n\n\tif len(c.Headers) == 0 {\n\t\tc.Headers = make([]map[string]string, 0)\n\t}\n\n\t// Validate and initialize attribs.\n\tif c.Attribs != nil {\n\t\tif _, err := json.Marshal(c.Attribs); err != nil {\n\t\t\treturn c, errors.New(a.i18n.T(\"subscribers.invalidJSON\"))\n\t\t}\n\t}","sourceCodeStart":709,"sourceCodeEnd":745,"githubUrl":"https://github.com/knadh/listmonk/blob/670c01717d48647093335cc23a6be6f4b79c3b6b/cmd/campaigns.go#L709-L745","documentation":"After checking a messenger fallback (only 'email-*' prefixed ones degrade to 'email'), validateCampaignFields rejects a messenger the manager doesn't have: if !a.manager.HasMessenger(c.Messenger) it returns fieldInvalidMessenger with the messenger name interpolated. It means the requested delivery channel (SMTP config, webhook, etc.) is not registered/available.","triggerScenarios":"CreateCampaign/UpdateCampaign/TestCampaign with a messenger value that no enabled messenger provides, e.g. a named SMTP ('email-smtp2') that was deleted or disabled, or a typo like 'emial'.","commonSituations":"Admin disabled or renamed an SMTP config after campaigns referenced it; messenger defined only in settings but the corresponding service isn't started; environment drift between staging and production messenger names.","solutions":["Use the default messenger 'email', or omit the messenger field if a default is acceptable.","Check Settings -> SMTP / messengers in the admin UI and re-enable or recreate the referenced messenger.","Re-create the missing SMTP config with the exact same name the campaigns use.","List available messengers (GET /api/settings) and pick one that exists."],"exampleFix":"// before\n{\"messenger\": \"email-old-smtp\"}\n// after\n{\"messenger\": \"email\"}","handlingStrategy":"fallback","validationCode":"// fetch available messengers first, then pick a valid one\nconst settings = await api.getSettings();\nconst messenger = settings.messengers?.includes(desired) ? desired : 'email';","typeGuard":"function isKnownMessenger(v: unknown, available: string[]): v is string {\n  return typeof v === 'string' && (v === 'email' || available.includes(v));\n}","tryCatchPattern":"try {\n  await api.createCampaign({ messenger, ...rest });\n} catch (e) {\n  if (e.message.includes('fieldInvalidMessenger')) {\n    // retry with the default messenger\n    await api.updateCampaign(id, { messenger: 'email' });\n  } else { throw e; }\n}","preventionTips":["Keep messenger names in configuration, not hard-coded in scripts.","After deleting/renaming an SMTP config, update or recreate campaigns referencing it.","Validate the messenger against GET /api/settings before submission.","Use the plain 'email' messenger when no special channel is needed."],"tags":["campaign","messenger","smtp","configuration"],"backgroundTag":"unknown-messenger-name","analyzedSha":"670c01717d48647093335cc23a6be6f4b79c3b6b","analyzedAt":"2026-09-01T03:39:35.452Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}