Billionmail/BillionMail · error
failed to import recipients (batch %d/%d): %w
Error message
failed to import recipients (batch %d/%d): %w
What it means
ImportRecipients inserts recipient rows into recipient_info in chunks using InsertIgnore. When any batch insert fails at the database level, the error is logged and wrapped as "failed to import recipients (batch %d/%d): %w", aborting the whole import. Because earlier batches were already committed, the import is left partially complete.
Source
Thrown at core/internal/service/batch_mail/batch_mail.go:246
// Prepare data for current batch
values := make([]g.Map, len(currentBatch))
for j, contact := range currentBatch {
values[j] = g.Map{
"task_id": taskId,
"recipient": contact.Email,
"is_sent": 0,
"sent_time": 0,
"message_id": "",
"create_time": now,
}
}
// Insert current batch
result, err := g.DB().Model("recipient_info").InsertIgnore(values)
if err != nil {
g.Log().Error(ctx, "Failed to import recipient batch %d/%d for task %d: %v",
i+1, totalBatches, taskId, err)
return fmt.Errorf("failed to import recipients (batch %d/%d): %w", i+1, totalBatches, err)
}
// Count affected rows
affected, err := result.RowsAffected()
if err != nil {
g.Log().Debugf(ctx, "Could not get affected rows for batch %d/%d: %v", i+1, totalBatches, err)
} else {
totalImported += int(affected)
}
}
g.Log().Info(ctx, "Task %d: Total %d recipients imported successfully", taskId, totalImported)
return nil
}
// ImportRecipientsTx
func ImportRecipientsTx(ctx context.Context, tx gdb.TX, taskId int, contacts []*entity.Contact) error {
if len(contacts) == 0 {View on GitHub (pinned to fc36c76c05)
Solutions
- Read the logged underlying DB error for the failing batch number
- Validate/normalize CSV rows (email format, field lengths, required columns) before importing
- Ensure the recipient_info schema matches the value maps (run migrations)
- Make imports resumable/idempotent (skip already-inserted batches via InsertIgnore semantics) and retry from the failed batch
Example fix
// before: abort entire import on first batch failure
if err != nil {
return fmt.Errorf("failed to import recipients (batch %d/%d): %w", i+1, totalBatches, err)
}
// after: validate rows before insert and report batch context
for _, v := range values {
if !isValidEmail(v["email"].(string)) {
return fmt.Errorf("invalid email in batch %d/%d: %s", i+1, totalBatches, v["email"])
}
}
if _, err := g.DB().Model("recipient_info").InsertIgnore(values); err != nil {
return fmt.Errorf("failed to import recipients (batch %d/%d): %w", i+1, totalBatches, err)
} Defensive patterns
Strategy: validation
Validate before calling
for _, r := range recipients {
if r.Email == "" || len(r.Email) > 254 || !strings.Contains(r.Email, "@") {
return fmt.Errorf("invalid recipient email: %q", r.Email)
}
} Try / catch
if err := ImportRecipients(ctx, taskId, recipients); err != nil {
log.Printf("import aborted: %v (earlier batches already committed)", err)
return err
} Prevention
- Validate CSV rows (email format, lengths, required fields) before import
- Run schema checks/migrations so recipient_info matches inserted value maps
- Insert in a transaction (ImportRecipientsTx) to avoid partial imports
- Log the batch index with the underlying driver error for quick diagnosis
When it happens
Trigger: Any batch's INSERT into recipient_info errors: schema mismatch between value maps and table columns, invalid/overlong field values (bad email, oversized custom fields), DB connection loss mid-import, or constraint violations not suppressed by InsertIgnore (e.g. NOT NULL without default).
Common situations: Importing a CSV with columns not matching recipient_info schema; multi-byte or malformed emails; Postgres restarted during a large import; duplicates are fine (InsertIgnore) but NOT NULL/length violations are not.
Related errors
- failed to insert alias: %v
- Batch insert mailbox failed (batch %d-%d): %w
- Failed to create email: %w
- enqueue video job: %w
- failed to get all domains: %w
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/525439ebff6fa6eb.
Report an issue: GitHub.