Billionmail/BillionMail · error
failed to query relay domain mappings: %v
Error message
failed to query relay domain mappings: %v
What it means
GetRelayDomains queries bm_relay_domain_mapping joined to bm_relay_config to list sender domains with an active relay config, returning a set used to skip DKIM signing setup for relay-mapped domains. This error wraps the SQL Scan failure. Callers (getDKIMRecordWithKeySize, RepairDKIMSigningConfig) receive nil and must handle the degraded state.
Source
Thrown at core/internal/service/domains/domains.go:376
return domains, err
}
// GetRelayDomains returns a set of domains that have active SMTP relay mappings.
// These domains should be excluded from local DKIM signing since the relay provider
// (e.g. SES, SendGrid) adds its own DKIM signature.
func GetRelayDomains(ctx context.Context) (map[string]bool, error) {
type mapping struct {
SenderDomain string `json:"sender_domain"`
}
var mappings []mapping
err := g.DB().Model("bm_relay_domain_mapping rdm").
LeftJoin("bm_relay_config rc", "rc.id = rdm.relay_id").
Where("rc.active", 1).
Fields("rdm.sender_domain").
Scan(&mappings)
if err != nil {
return nil, fmt.Errorf("failed to query relay domain mappings: %v", err)
}
result := make(map[string]bool, len(mappings))
for _, m := range mappings {
domain := strings.TrimPrefix(m.SenderDomain, "@")
if domain != "" {
result[domain] = true
}
}
return result, nil
}
func Exists(ctx context.Context, domainName string) (bool, error) {
count, err := g.DB().Model("domain").
Ctx(ctx).
Where("domain", domainName).
Count()
View on GitHub (pinned to fc36c76c05)
Solutions
- Check the wrapped %v error for 'relation does not exist' → run the schema migrations for bm_relay_domain_mapping / bm_relay_config
- Verify PostgreSQL connectivity and credentials
- Confirm both tables and the rc.active and rdm.sender_domain columns exist with expected names
- As a stopgap, treat relay lookup failure as non-fatal for DKIM reads and log a warning
Example fix
// before
if err != nil { return nil, fmt.Errorf("failed to query relay domain mappings: %v", err) }
// after
if err != nil {
logger.Warnf(ctx, "relay domain lookup failed: %v — assuming no relay domains", err)
return map[string]bool{}, nil // degrade gracefully for DKIM read paths
} Defensive patterns
Strategy: fallback
Validate before calling
exists, err := g.DB().Model("information_schema.tables").Where("table_name", "bm_relay_domain_mapping").Count()
if err != nil || exists == 0 { return map[string]bool{}, nil } // schema not migrated yet Try / catch
relayDomains, relayErr := GetRelayDomains(ctx)
if relayErr != nil {
logger.Warnf(ctx, "relay lookup failed, assuming empty: %v", relayErr)
relayDomains = map[string]bool{}
} Prevention
- Run schema migrations for bm_relay_* tables before enabling DKIM features
- Add the relay query to DB connectivity smoke tests
- Treat relay lookup as advisory on read paths, required on repair paths
- Keep table/column names in one consts/model layer to avoid drift
When it happens
Trigger: Any DKIM record/repair flow touching a domain when the SELECT rdm.sender_domain FROM bm_relay_domain_mapping rdm LEFT JOIN bm_relay_config rc ... fails — table missing (schema not migrated), DB down, or malformed query/column rename.
Common situations: Older deployments missing bm_relay_* tables; failed migration; DB credentials expired; column renamed in an upgrade causing SQL syntax error.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- failed to get contacts trend: %w
- failed to get all domains: %v
- getSenderIdentitiesForIp err: %v
- failed to get recipient count: %w
- failed to get all domains: %w
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/a4a7edf9e3e1019c.
Report an issue: GitHub.