Billionmail/BillionMail · error
Failed to update abnormal recipient: %w
Error message
Failed to update abnormal recipient: %w
What it means
Within BatchUpsertAbnormalRecipients, existing recipients are updated with count+1/description/add_type. If that UPDATE statement fails (deadlock, lock timeout, connection reset, constraint violation), this wrapped error aborts the remaining batch.
Source
Thrown at core/internal/service/abnormal_recipient/abnormal_recipient.go:115
var existList []entity.AbnormalRecipient
err := g.DB().Model("abnormal_recipient").WhereIn("recipient", recipients).Scan(&existList)
if err != nil {
return fmt.Errorf("Failed to query existing abnormal recipients: %w", err)
}
existMap := make(map[string]*entity.AbnormalRecipient)
for _, r := range existList {
existMap[r.Recipient] = &r
}
// 1. Update the existing one count+1
for _, r := range existList {
_, err := g.DB().Model("abnormal_recipient").Where("id", r.Id).Data(g.Map{
"count": r.Count + 1,
"description": description,
"add_type": addType,
}).Update()
if err != nil {
return fmt.Errorf("Failed to update abnormal recipient: %w", err)
}
}
// 2. Inserting something that doesn't exist
var insertList []g.Map
for _, recipient := range recipients {
if _, ok := existMap[recipient]; !ok {
insertList = append(insertList, g.Map{
"recipient": recipient,
"count": 1,
"add_type": addType,
"description": description,
"create_time": now,
})
}
}
if len(insertList) > 0 {
View on GitHub (pinned to fc36c76c05)
Solutions
- Retry the whole batch on serialization/deadlock errors (SQLSTATE 40P01, 40001).
- Serialize concurrent writers or use a lock (advisory lock / SELECT FOR UPDATE).
- Verify schema columns count/description/add_type match the entity.
- Check connection pool settings for idle timeouts.
Example fix
// before
_ = abnormal_recipient.BatchUpsertAbnormalRecipients(ctx, recipients, addType, desc)
// after
err := abnormal_recipient.BatchUpsertAbnormalRecipients(ctx, recipients, addType, desc)
if err != nil && isRetryableSQLState(err) {
err = abnormal_recipient.BatchUpsertAbnormalRecipients(ctx, recipients, addType, desc)
} Defensive patterns
Strategy: retry
Try / catch
err := abnormal_recipient.BatchUpsertAbnormalRecipients(ctx, recs, addType, desc)
if err != nil {
var pqErr *pq.Error
if errors.As(err, &pqErr) && (pqErr.Code == "40P01" || pqErr.Code == "40001") {
// deadlock/serialization: retry the whole batch once
}
} Prevention
- Avoid concurrent batch upserts on the same rows (use a job lock)
- Keep transactions short
- Set a sane deadlock_timeout and monitor deadlocks
When it happens
Trigger: Concurrent batch upserts updating the same rows (deadlock/serialization failure); DB connection dropped mid-loop; column mismatch after schema change.
Common situations: Two cron jobs (e.g. AbnormalRecipientAutoStat and a manual import) running simultaneously; long transactions holding row locks; postgres restart during a large import.
Related errors
- Failed to add exception recipient: %w
- Failed to remove exception recipient: %w
- Failed to get exception recipient: %w
- Failed to query existing abnormal recipients: %w
- Failed to insert abnormal recipients: %w
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/7ae9ef12d4dbf8db.
Report an issue: GitHub.