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

  1. Check the wrapped %v error for 'relation does not exist' → run the schema migrations for bm_relay_domain_mapping / bm_relay_config
  2. Verify PostgreSQL connectivity and credentials
  3. Confirm both tables and the rc.active and rdm.sender_domain columns exist with expected names
  4. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/a4a7edf9e3e1019c. Report an issue: GitHub.