Billionmail/BillionMail · error

No SPF record found (from cache)

Error message

No SPF record found (from cache)

What it means

GetRealSPFRecord looks up the domain's SPF (v=spf1 TXT) record and caches results; a previous lookup for this domain already failed and stored the sentinel 'not_found' value. When the cache is hit, the function returns this cached negative result instead of re-querying DNS. It is a cached version of error [45]/[48].

Source

Thrown at core/internal/controller/relay/relay_v1_list_relay_configs.go:181

	if host != "" {
		include := "include:" + host
		return strings.Contains(spf, include)
	}
	return false
}

var (
	spfCache = gcache.New()
	mu       = &sync.Mutex{}
)

func GetRealSPFRecord(ctx context.Context, domain string) (string, error) {
	cacheKey := fmt.Sprintf("real_spf_record:%s", domain)

	if value, _ := spfCache.Get(ctx, cacheKey); value != nil {

		if value.String() == "not_found" {
			return "", fmt.Errorf("No SPF record found (from cache)")
		}
		return value.String(), nil
	}

	mu.Lock()
	defer mu.Unlock()

	if value, _ := spfCache.Get(ctx, cacheKey); value != nil {
		if value.String() == "not_found" {
			return "", fmt.Errorf("No SPF record found (from cache)")
		}
		return value.String(), nil
	}

	var spf string
	var finalErr error
	txts, err := net.LookupTXT(domain)
	if err != nil {

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify with 'dig TXT yourdomain.com' that an spf1 record exists; add one if missing (v=spf1 ...)
  2. Wait 2 minutes for the negative cache entry to expire and retry
  3. Confirm you are querying the sending domain, not a subdomain
  4. Clear the app cache or restart if you need an immediate re-check
Defensive patterns

Strategy: fallback

Validate before calling

// check SPF presence out-of-band before relying on the API
dig +short TXT example.com | grep -q 'v=spf1'

Try / catch

try {
  spf = await api.getRealSPFRecord(domain);
} catch (e) {
  if (e.message.includes('No SPF record')) {
    spf = null; // proceed without SPF, flag domain for setup
    markDomainNeedsSPF(domain);
  }
}

Prevention

When it happens

Trigger: Calling ListRelayConfigs (which resolves SPF) for a domain whose earlier DNS TXT lookup produced no v=spf1 record within the last 2 minutes, so spfCache holds 'not_found'.

Common situations: Domain genuinely has no SPF record (never configured); querying the wrong domain (e.g. MX-less subdomain); negative cache masking a transient DNS outage that happened 2 minutes ago.

Related errors


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