{"record":{"id":"534a6402928a006b","repo":"Billionmail/BillionMail","slug":"error-reading-csv-file-v","errorCode":null,"errorMessage":"error reading CSV file: %v","messagePattern":"error reading CSV file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/controller/contact/contact.go","lineNumber":101,"sourceCode":"\n\t//fmt.Printf(\"parseTXTFile - Total valid contacts: %d\\n\", len(contacts))\n\treturn contacts, nil\n}\n\n// parseCSVFile parses CSV file content\nfunc parseCSVFile(fileContent []byte) ([]*entity.Contact, error) {\n\t// handle possible BOM\n\tfileContent = bytes.TrimPrefix(fileContent, []byte(\"\\xef\\xbb\\xbf\"))\n\n\treader := csv.NewReader(bytes.NewReader(fileContent))\n\treader.FieldsPerRecord = -1 // Allow different number of fields per line\n\treader.TrimLeadingSpace = true\n\treader.LazyQuotes = true  // Allow non-strict quotes\n\treader.ReuseRecord = true // Reuse record to improve performance\n\n\trecords, err := reader.ReadAll()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading CSV file: %v\", err)\n\t}\n\n\tvar contacts []*entity.Contact\n\tvar hasHeader bool\n\n\t// Check if header exists\n\tif len(records) > 0 {\n\t\tfirstRow := records[0]\n\t\tif len(firstRow) >= 1 && strings.ToLower(firstRow[0]) == \"email\" {\n\t\t\thasHeader = true\n\t\t}\n\t}\n\n\t// Process records\n\tstartIndex := 0\n\tif hasHeader {\n\t\tstartIndex = 1\n\t}","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/controller/contact/contact.go#L83-L119","documentation":"parseCSVFile reads all records with encoding/csv's reader.ReadAll() after enabling TrimLeadingSpace, LazyQuotes, and ReuseRecord. If the CSV tokenizer hits a structural problem — e.g. a bare quote mid-field, a quote not followed by a delimiter/newline, or an extraneous or missing quote — ReadAll returns a csv.ParseError and it is wrapped with this message. The wrapper discards the underlying error's line context in the string, though the %v verb keeps the wrapped text.","triggerScenarios":"Uploading a contacts CSV where a field contains an unescaped quote (LazyQuotes only forgives some cases), a quote character is not immediately followed by a comma/newline, or the file mixes line endings with stray quotes. Any ReadAll parse error on the uploaded bytes.","commonSituations":"CSVs exported from Excel with embedded quotes in names; user-edited CSVs with mismatched quotes; TSV or semicolon-separated files mislabeled as CSV; files pasted from email clients introducing smart quotes (U+201C/U+201D) that csv.Reader treats as invalid.","solutions":["Open the CSV and fix the malformed quoting on the reported line; the wrapped error text (kept via %v) includes the line/column.","Re-export the file from the source tool with proper quoting (quote all fields).","Consider wrapping with %w instead of %v so callers can errors.As(csv.ParseError) and report an exact row to the user.","If files use a different delimiter, set reader.Comma before ReadAll; non-comma delimiters can cause quote-parse errors.","If the file may be huge, switch from ReadAll to reader.Read() streaming to avoid memory pressure (does not fix parse errors but avoids OOM-path failures)."],"exampleFix":"// before\nrecords, err := reader.ReadAll()\nif err != nil {\n    return nil, fmt.Errorf(\"error reading CSV file: %v\", err)\n}\n// after\nrecords, err := reader.ReadAll()\nif err != nil {\n    var perr *csv.ParseError\n    if errors.As(err, &perr) {\n        return nil, fmt.Errorf(\"error reading CSV file at line %d, column %d: %w\", perr.Line, perr.Column, err)\n    }\n    return nil, fmt.Errorf(\"error reading CSV file: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"// cheap pre-checks before parsing:\nif len(fileContent) == 0 { return errors.New(\"empty CSV file\") }\nsniff := string(fileContent[:min(1024, len(fileContent))])\n// reject obvious binary content uploaded as CSV\nif strings.ContainsRune(sniff, 0) { return errors.New(\"file is not valid CSV text\") }","typeGuard":null,"tryCatchPattern":"records, err := parseCSVFile(data)\nif err != nil {\n    var perr *csv.ParseError\n    if errors.As(err, &perr) {\n        return fmt.Errorf(\"invalid CSV at line %d, column %d — fix quoting and re-upload\", perr.Line, perr.Column)\n    }\n    return fmt.Errorf(\"CSV import failed: %w\", err)\n}","preventionTips":["Quote all CSV fields on export from Excel/Google Sheets","Replace smart quotes (U+201C/U+201D) with ASCII quotes before import","Keep LazyQuotes enabled and consider setting reader.Comma explicitly","Surface csv.ParseError line/column to end users instead of a generic message"],"tags":["csv","parsing","file-upload"],"backgroundTag":"csv-parse-error","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}