knadh/listmonk · error

'email' column not found

Error message

'email' column not found

What it means

LoadCSV parses a subscriber import CSV and requires an 'email' column to map records to subscribers. Before importing any rows it maps CSV headers to known field keys via mapCSVHeaders and checks that an 'email' header exists. If the header is missing, the import is aborted immediately with this error because no subscriber could be created or identified.

Source

Thrown at internal/subimporter/importer.go:509

	s.im.Unlock()

	// Rewind, now that we've done a linecount on the same handler.
	_, _ = f.Seek(0, 0)
	rd := csv.NewReader(f)
	rd.Comma = delim

	// Read the header.
	csvHdr, err := rd.Read()
	if err != nil {
		s.log.Printf("error reading header from '%s': '%v'", srcPath, err)
		return err
	}

	hdrKeys := s.mapCSVHeaders(csvHdr, csvHeaders)
	// email is a required header.
	if _, ok := hdrKeys["email"]; !ok {
		s.log.Printf("'email' column not found in '%s'", srcPath)
		return errors.New("'email' column not found")
	}

	var (
		lnHdr = len(hdrKeys)
		i     = 0
	)
	for {
		i++

		// Check for the stop signal.
		select {
		case <-s.im.stop:
			failed = false
			close(s.subQueue)
			s.log.Println("stop request received")
			return nil
		default:
		}

View on GitHub (pinned to 670c01717d)

Solutions

  1. Add a column named exactly 'email' to the CSV header row (check for typos, extra spaces, or a BOM on the first cell).
  2. Re-export the CSV ensuring the header row is included and the email column is labeled 'email'.
  3. If the source system uses a different label, rename the column in the file or preprocess it before upload.
  4. Open the first line of the file in a text editor to confirm a header row exists at all.

Example fix

// before
name,company
John,Acme
// after
email,name,company
john@acme.com,John,Acme
Defensive patterns

Strategy: validation

Validate before calling

f, _ := os.Open(srcPath)
r := csv.NewReader(f)
hdr, err := r.Read()
if err != nil { return err }
found := false
for _, h := range hdr {
    if strings.EqualFold(strings.TrimSpace(h), "email") { found = true; break }
}
if !found {
    return fmt.Errorf("CSV %s has no 'email' header column", srcPath)
}

Prevention

When it happens

Trigger: Calling LoadCSV (or the admin import API) with a CSV file whose header row lacks an 'email' column — e.g. headers like 'mail', 'e-mail', 'Email Address', or a file with no header row at all.

Common situations: Exporting subscribers from another ESP with differently named columns; uploading a data-only CSV after someone deleted the header line; case/whitespace mismatches or a BOM on the first cell that break header matching.

Related errors


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