{"record":{"id":"e47a02a0dee7e5bf","repo":"Billionmail/BillionMail","slug":"failed-to-insert-abnormal-recipients-w","errorCode":null,"errorMessage":"Failed to insert abnormal recipients: %w","messagePattern":"Failed to insert abnormal recipients: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/abnormal_recipient/abnormal_recipient.go","lineNumber":137,"sourceCode":"\t// 2. Inserting something that doesn't exist\n\tvar insertList []g.Map\n\tfor _, recipient := range recipients {\n\t\tif _, ok := existMap[recipient]; !ok {\n\t\t\tinsertList = append(insertList, g.Map{\n\t\t\t\t\"recipient\":   recipient,\n\t\t\t\t\"count\":       1,\n\t\t\t\t\"add_type\":    addType,\n\t\t\t\t\"description\": description,\n\t\t\t\t\"create_time\": now,\n\t\t\t})\n\t\t}\n\t}\n\tif len(insertList) > 0 {\n\n\t\t_, err := g.DB().Model(\"abnormal_recipient\").Data(insertList).InsertIgnore()\n\t\tif err != nil {\n\n\t\t\treturn fmt.Errorf(\"Failed to insert abnormal recipients: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// BatchUpsertAbnormalRecipientsWithDetails\nfunc BatchUpsertAbnormalRecipientsWithDetails(ctx context.Context, recipientDetails []RecipientDetail, addType int, baseDescription string) error {\n\tnow := time.Now().Unix()\n\n\tif len(recipientDetails) == 0 {\n\t\treturn nil\n\t}\n\n\trecipients := make([]string, len(recipientDetails))\n\tdetailsMap := make(map[string]RecipientDetail)\n\tfor i, detail := range recipientDetails {\n\t\trecipients[i] = detail.Email","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/abnormal_recipient/abnormal_recipient.go#L119-L155","documentation":"The final step of BatchUpsertAbnormalRecipients bulk-inserts new recipients via Data(insertList).InsertIgnore(). If the multi-row INSERT fails at SQL level, this wrapped error is returned, leaving earlier updates in the batch already applied (no transaction).","triggerScenarios":"DB unreachable during insert; a required column missing from the map (schema drift); malformed recipient value violating a constraint InsertIgnore does not cover (e.g. NOT NULL on other columns); statement size limits on huge batches.","commonSituations":"Importing thousands of recipients in one statement and hitting postgres parameter limits; partial batch state after a mid-loop update failure on a previous run.","solutions":["Chunk the insert list (e.g. 500-1000 rows).","Ensure insertList rows contain all required NOT NULL columns.","Run the update+insert phases inside a transaction so the batch is atomic.","Verify abnormal_recipient schema matches the g.Map keys."],"exampleFix":"// before\n_, err := g.DB().Model(\"abnormal_recipient\").Data(insertList).InsertIgnore()\n// after\ntx, _ := g.DB().Begin(ctx)\n_, err := tx.Model(\"abnormal_recipient\").Data(insertList).InsertIgnore()\nif err != nil { tx.Rollback(); return err }\ntx.Commit()","handlingStrategy":"validation","validationCode":"// before the insert phase\nfor _, m := range insertList {\n\tif m[\"recipient\"] == nil || m[\"recipient\"] == \"\" { return errors.New(\"blank recipient row\") }\n}","typeGuard":null,"tryCatchPattern":"_, err := g.DB().Model(\"abnormal_recipient\").Data(insertList).InsertIgnore()\nif err != nil { return fmt.Errorf(\"bulk insert %d recipients: %w\", len(insertList), err) }","preventionTips":["Chunk inserts to ~500 rows","Fill all NOT NULL columns in each g.Map","Wrap update+insert in one transaction for atomicity"],"tags":["database","goframe","insert-failure"],"backgroundTag":"database-insert-failed","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"}