{"record":{"id":"f74585f7ad064763","repo":"Billionmail/BillionMail","slug":"getsenderidentitiesforip-err-v","errorCode":null,"errorMessage":"getSenderIdentitiesForIp err: %v","messagePattern":"getSenderIdentitiesForIp err: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/warmup/sender_ip_warmup.go","lineNumber":41,"sourceCode":"\tminSendVolumeForFullScoring = 20                 // The minimum sending volume required for a full score calculation\n)\n\ntype SenderIpWarmupService struct{}\n\nvar insSenderIpWarmupService = SenderIpWarmupService{}\n\nfunc SenderIpWarmup() *SenderIpWarmupService {\n\treturn &insSenderIpWarmupService\n}\n\n// getSenderIdentitiesForIp gets the associated sender identities (e.g., email addresses or domains) for a given sender IP.\nfunc (s *SenderIpWarmupService) getSenderIdentitiesForIp(ctx context.Context, senderIp string) (domains []string, err error) {\n\t// Get the sender identities associated with this IP.\n\tvar vals []gdb.Value\n\tvals, err = g.DB().Ctx(ctx).Model(\"domain\").Where(\"active = 1\").Fields(\"domain\").Array(\"domain\")\n\n\tif err != nil {\n\t\terr = fmt.Errorf(\"getSenderIdentitiesForIp err: %v\", err)\n\t\treturn\n\t}\n\n\tfor _, v := range vals {\n\t\tdomains = append(domains, v.String())\n\t}\n\n\tg.Log().Debug(ctx, \"Domains for IP\", senderIp, domains)\n\n\treturn // return empty, let the scoring logic handle the absence of data\n}\n\n// InitializeOrGetWarmupStatus initializes or retrieves the warmup status of an IP.\nfunc (s *SenderIpWarmupService) InitializeOrGetWarmupStatus(ctx context.Context, senderIp string) (record *entity.SenderIpWarmup, err error) {\n\terr = g.DB().Model(\"bm_sender_ip_warmup\").Ctx(ctx).Where(\"sender_ip\", senderIp).Scan(&record)\n\tif err != nil {\n\t\tg.Log().Errorf(ctx, \"Failed to query SenderIpWarmup for IP %s: %v\", senderIp, err)\n\t\treturn","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/warmup/sender_ip_warmup.go#L23-L59","documentation":"getSenderIdentitiesForIp in the warmup service queries the 'domain' table (active = 1) for all sender-identity domain names. If the GoFrame DB query fails — connection refused, bad credentials, missing table/column, or context cancellation — the error is wrapped as 'getSenderIdentitiesForIp err' and propagated to EvaluateScoreForProvider and EvaluateIpScore. It indicates the warmup scoring pipeline could not load domains from the database.","triggerScenarios":"PostgreSQL/DB down or unreachable, wrong DB credentials in config, 'domain' table or 'active'/'domain' columns missing or renamed after a migration, query context cancelled by shutdown or deadline.","commonSituations":"Fresh deployment where migrations didn't run, misconfigured database DSN, DB connection pool exhausted, schema drift between code and migrations during upgrades.","solutions":["Check the wrapped error for the concrete DB cause (connection vs SQL syntax vs missing column).","Verify DB connectivity and credentials (g.DB() config, psql test).","Run pending migrations; confirm the domain table has active and domain columns.","Check DB logs at query time for lock/pool exhaustion.","Add reconnect/pool health checks if failures are intermittent."],"exampleFix":"// before\nvals, err = g.DB().Ctx(ctx).Model(\"domain\").Where(\"active = 1\").Fields(\"domain\").Array(\"domain\")\nif err != nil {\n    err = fmt.Errorf(\"getSenderIdentitiesForIp err: %v\", err)\n    return\n}\n// after\nvals, err = g.DB().Ctx(ctx).Model(\"domain\").Where(\"active = 1\").Fields(\"domain\").Array(\"domain\")\nif err != nil {\n    err = fmt.Errorf(\"getSenderIdentitiesForIp err: %w\", err)\n    return\n}","handlingStrategy":"retry","validationCode":"// health-check the DB before running warmup scoring\nif err := g.DB().Ctx(ctx).Exec(\"SELECT 1\"); err != nil {\n    return fmt.Errorf(\"database unavailable: %w\", err)\n}\n// verify schema exists\nn, err := g.DB().Ctx(ctx).Model(\"domain\").Count()\nif err != nil {\n    return fmt.Errorf(\"domain table missing/unreadable: %w\", err)\n}\n_ = n","typeGuard":null,"tryCatchPattern":"domains, err := svc.getSenderIdentitiesForIp(ctx, ip)\nif err != nil {\n    if ctx.Err() != nil {\n        return fmt.Errorf(\"warmup scoring cancelled: %w\", ctx.Err())\n    }\n    // transient DB error: retry with backoff\n    return fmt.Errorf(\"warmup scoring skipped: %w\", err)\n}","preventionTips":["Run migrations as part of deployment and verify the domain schema","Add DB health checks/readiness probes before starting warmup workers","Set sane connection-pool limits and monitor pool saturation","Use %w instead of %v when wrapping so errors.As/Is work"],"tags":["database","sql","warmup"],"backgroundTag":"database-query-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}