Billionmail/BillionMail · warning

unsupported file type: %s

Error message

unsupported file type: %s

What it means

parseContactFile dispatches file parsing by a file-type string: 'txt', 'csv', or 'excel'. When the provided fileType matches none of these, it returns this sentinel error instead of guessing a parser. It is an input-validation guard, not an I/O or data error.

Source

Thrown at core/internal/controller/contact/contact.go:53

	MaxPageSize     = 100
)

// parseContactFile parses contact file content based on file type
func parseContactFile(fileContent []byte, fileType string) ([]*entity.Contact, error) {

	// if txt format, split by line
	if fileType == "txt" {
		return parseTXTFile(fileContent)
	}
	// CSV format
	if fileType == "csv" {
		return parseCSVFile(fileContent)
	}
	// Excel format
	if fileType == "excel" {
		return parseExcelFile(fileContent)
	}
	return nil, fmt.Errorf("unsupported file type: %s", fileType)
}

// parseTXTFile parses txt file content, one email per line
func parseTXTFile(fileContent []byte) ([]*entity.Contact, error) {
	//fmt.Printf("parseTXTFile - Content length: %d bytes\n", len(fileContent))
	//fmt.Printf("parseTXTFile - Content as string: %s\n", string(fileContent))

	var contacts []*entity.Contact
	lines := bytes.Split(fileContent, []byte("\n"))

	for _, line := range lines {
		// remove whitespace characters
		email := strings.TrimSpace(string(line))

		if email == "" {
			continue
		}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Normalize and map the fileType before calling: lower-case it and map 'xlsx'/'xls' -> 'excel', strip leading dots.
  2. Fix the client to send one of the three supported values: txt, csv, excel.
  3. Optionally extend parseContactFile with additional parsers (e.g. real xlsx via excelize) if a new format must be supported.
  4. Log the offending value so the client can be corrected; the message already includes %s.

Example fix

// before
if fileType == "excel" {
    return parseExcelFile(fileContent)
}
return nil, fmt.Errorf("unsupported file type: %s", fileType)
// after
fileType = strings.ToLower(strings.TrimPrefix(strings.TrimSpace(fileType), "."))
if fileType == "xlsx" || fileType == "xls" {
    fileType = "excel"
}
switch fileType {
case "txt":
    return parseTXTFile(fileContent)
case "csv":
    return parseCSVFile(fileContent)
case "excel":
    return parseExcelFile(fileContent)
}
return nil, fmt.Errorf("unsupported file type: %s", fileType)
Defensive patterns

Strategy: validation

Validate before calling

var supportedTypes = map[string]bool{"txt": true, "csv": true, "excel": true}
func isSupportedFileType(ft string) bool {
    return supportedTypes[strings.ToLower(strings.TrimSpace(ft))]
}
// call before parsing:
// if !isSupportedFileType(fileType) { reject request with 400 }

Prevention

When it happens

Trigger: An ImportContacts-style request supplies a fileType other than exactly "txt", "csv", or "excel" — e.g. "xlsx", "xls", "TXT" (uppercase), "vcard", or an empty string from an unset form field.

Common situations: Frontend sends the raw file extension ('.csv') instead of the bare type ('csv'); client uses 'xlsx' while the backend only recognizes 'excel'; new file types added client-side before server support; case differences from browser-provided MIME-derived types.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/0e3e3a03a3b925cc. Report an issue: GitHub.