knadh/listmonk · error
campaigns.fieldInvalidListIDs
Error message
campaigns.fieldInvalidListIDs
What it means
validateCampaignFields requires at least one target list: if len(c.ListIDs) == 0 it returns campaigns.fieldInvalidListIDs. A campaign is only meaningful when addressed to subscriber lists, so the empty case is rejected.
Source
Thrown at cmd/campaigns.go:719
c.ContentType != models.CampaignContentTypePlain &&
c.ContentType != models.CampaignContentTypeVisual &&
c.ContentType != models.CampaignContentTypeMarkdown {
c.ContentType = models.CampaignContentTypeRichtext
}
if c.ContentType != models.CampaignContentTypeVisual {
c.BodySource.Valid = false
}
// If there's a "send_at" date, it should be in the future.
if c.SendAt.Valid {
if c.SendAt.Time.Before(time.Now()) {
return c, errors.New(a.i18n.T("campaigns.fieldInvalidSendAt"))
}
}
if len(c.ListIDs) == 0 {
return c, errors.New(a.i18n.T("campaigns.fieldInvalidListIDs"))
}
if !a.manager.HasMessenger(c.Messenger) {
// If it's a specific SMTP, but it's no longer available (removed/disabled), fall back to general email messenger.
if strings.HasPrefix(c.Messenger, "email-") {
c.Messenger = "email"
} else {
return c, errors.New(a.i18n.Ts("campaigns.fieldInvalidMessenger", "name", c.Messenger))
}
}
camp := models.Campaign{Body: c.Body, TemplateBody: tplTag}
if err := c.CompileTemplate(a.manager.TemplateFuncs(&camp)); err != nil {
return c, errors.New(a.i18n.Ts("campaigns.fieldInvalidBody", "error", err.Error()))
}
if len(c.Headers) == 0 {
c.Headers = make([]map[string]string, 0)View on GitHub (pinned to 670c01717d)
Solutions
- Include at least one valid list ID in the lists array of the request.
- Create a list first (POST /api/lists) if none exists, then reference its ID.
- In the UI, disable submit until a list is selected; validate client-side.
- Verify list IDs are integers and that the array is non-null.
Example fix
// before
{"name": "News", "lists": []}
// after
{"name": "News", "lists": [1, 3]} Defensive patterns
Strategy: validation
Validate before calling
function requireLists(listIds) {
if (!Array.isArray(listIds) || listIds.length === 0) {
throw new Error('at least one list id is required');
}
if (!listIds.every(n => Number.isInteger(n) && n > 0)) {
throw new Error('all list ids must be positive integers');
}
} Type guard
function hasListIds(v: unknown): v is number[] {
return Array.isArray(v) && v.length > 0 && v.every((n): n is number => Number.isInteger(n));
} Try / catch
try {
await api.createCampaign({ lists: listIds, ...rest });
} catch (e) {
if (e.message.includes('fieldInvalidListIDs')) {
throw new Error('Select at least one subscriber list before creating the campaign');
}
throw e;
} Prevention
- Enforce list selection in the UI before enabling submit.
- Ensure list IDs are integers, not stringified IDs.
- Validate that referenced lists still exist (they may have been deleted).
When it happens
Trigger: CreateCampaign, UpdateCampaign, or TestCampaign with 'lists' (ListIDs) missing, empty array, or null in the request body.
Common situations: Front-end allowing campaign creation before the user selects recipients; automation scripts copying payloads that had lists stripped; sending list IDs as strings instead of integers and ending up with an empty parsed array.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- campaigns.fieldInvalidFromEmail
- campaigns.fieldInvalidName
- campaigns.fieldInvalidSubject
- campaigns.fieldInvalidSendAt
- campaigns.fieldInvalidBody
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/80984ad29bb877d8.
Report an issue: GitHub.