How to fix SPF permerror (too many DNS lookups)?
SPF permerror means your SPF record exceeds the 10 DNS lookup limit. Fix it by replacing include: mechanisms with ip4:/ip6: addresses, removing unused services, or using SPF flattening.
Detailed Answer
SPF PermError is the most common and most misunderstood SPF failure mode. A receiver that encounters PermError treats SPF as though it produced no result at all, which usually means DMARC falls back to DKIM (if DKIM aligns) or fails outright. If your domain sits behind a PermError, your SPF is effectively broken even though the DNS record exists and looks correct. Fixing it requires understanding what triggered the error and, often, some careful surgery on your DNS.
What "PermError" actually means
RFC 7208 defines five SPF results: Pass, Fail, SoftFail, Neutral, and PermError/TempError. PermError means the receiver could not evaluate the record because of a permanent problem — a syntax error, too many lookups, too many void lookups, or a combination. "Permanent" in this context means "the answer will not be different if I retry in an hour."
The most common causes, in rough order of frequency:
- More than 10 DNS lookups. This is by far the leading cause.
- More than 2 void lookups. A void lookup is a DNS query that returns NXDOMAIN or NODATA.
- Multiple SPF records on the same domain. RFC 7208 says there must be exactly one.
- Syntax errors — an include that points at a nonexistent domain, a malformed mechanism, a stray space.
- An
includethat itself triggers PermError — errors propagate.
The 10-lookup limit, in detail
Every include, a, mx, ptr, exists, and redirect mechanism causes one DNS lookup. Each include then recursively counts the lookups inside the included record. ip4 and ip6 do not count.
A typical pile-up:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:_spf.salesforce.com include:sendgrid.net include:spf.protection.outlook.com ~all
_spf.google.com→ 4 lookupsservers.mcsv.net→ 3 lookups_spf.salesforce.com→ 3 lookupssendgrid.net→ 1 lookupspf.protection.outlook.com→ 3 lookups
Total: 14. Over the limit. PermError.
Diagnosing the problem
Run your record through dig and count manually, or use any SPF introspection tool:
dig +short TXT example.com | grep spf1
For each include, recurse and count. This gets tedious fast, which is why the introspection tools exist.
If you see "too many DNS lookups" in a report or a rejection, that is PermError code 2.
Fix strategy 1: remove what you do not use
Go through every include and identify what it is for. "We used Mailchimp two years ago" is a common finding. Remove unused includes. This is the cleanest fix and has no side effects.
Fix strategy 2: flatten
SPF flattening replaces include:_spf.google.com with the actual ip4 and ip6 ranges that Google publishes. The result is:
v=spf1 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ... ~all
Zero lookups, no PermError. Drawback: if Google changes their ranges (rare but happens), your SPF silently stops authorizing their new IPs and mail fails SPF. You need either automated monitoring or a manual review cadence.
Do not flatten SendGrid, Mailchimp, or other ESPs with large dynamic IP pools unless you run automation that re-flattens nightly. Flattening a rarely-changing include like Google Workspace or Microsoft 365 is safer.
Fix strategy 3: consolidate sending sources
If you send transactional mail from SendGrid, marketing from Mailchimp, and support replies from HelpScout, consider routing everything through one platform. Fewer includes, simpler SPF, easier DMARC alignment.
Fix strategy 4: use a subdomain for marketing
Put marketing mail on mail.example.com with its own SPF record that includes the marketing ESP, and keep the root domain SPF minimal. DMARC alignment still works because of the relaxed alignment mode — if both domains share the same organizational domain, DMARC passes.
This requires:
example.com. TXT "v=spf1 include:spf.protection.outlook.com ~all"
mail.example.com. TXT "v=spf1 include:_spf.mailchimp.com ~all"
And your marketing platform must send From addresses on mail.example.com, not on the root.
Fix strategy 5: drop redundant includes
Many SPF records were generated by copy-paste and contain redundant or overlapping includes. include:_spf.google.com and include:_netblocks.google.com overlap. include:spf.protection.outlook.com already contains the ranges for Office 365; you do not need a separate include:mail.office365.com.
Multiple SPF records on one domain
RFC 7208 forbids multiple TXT records that each start with v=spf1. If you have:
example.com. TXT "v=spf1 include:_spf.google.com ~all"
example.com. TXT "v=spf1 include:sendgrid.net ~all"
That is PermError, even though each record individually is valid. Merge them into one:
example.com. TXT "v=spf1 include:_spf.google.com include:sendgrid.net ~all"
This sometimes happens when two teams add records independently. Always audit TXT records for duplicates.
Void lookup limit
RFC 7208 says a receiver MAY treat more than 2 void lookups as PermError. An include that points at a nonexistent domain, or an a mechanism for a domain with no A record, triggers a void lookup. If your SPF record includes a dead domain, remove the mechanism.
The "TempError vs PermError" distinction
TempError means the receiver could not resolve something due to a transient issue (timeout, DNS server down). Retry and it might work. PermError is a hard failure that does not go away on retry. If you see TempError intermittently, the problem is with a DNS server you do not control — often a slow include. Consider replacing it.
The 512-byte UDP limit — less relevant but worth knowing
A TXT record that exceeds 255 characters must be split into multiple strings (DNS allows chunks of up to 255 octets per string). Most DNS APIs handle this automatically. If you hand-edit a zone file, quote-split correctly:
"v=spf1 ip4:1.2.3.0/24 ip4:1.2.4.0/24 ... " "ip4:1.2.5.0/24 ~all"
Not split: syntax error. Over 255 with no split: zone serial failure on many nameservers.
Troubleshooting script
A short shell recipe to count lookups:
dig +short TXT example.com | grep -o 'include:[a-zA-Z0-9._-]*' | \
while read inc; do
dom=${inc#include:}
echo -n "$dom: "
dig +short TXT $dom | grep -oE '(include|a|mx|ptr|exists|redirect):' | wc -l
done
Sum the second column. If it plus your direct mechanisms is more than 10, you are over.
When to use IntoDNS.ai
IntoDNS.ai walks your SPF record, counts every lookup (including recursively through includes), identifies the offending mechanisms, and suggests the specific includes to remove or flatten. If your record has multiple TXT entries or hidden void lookups, it reports those too, with the exact DNS change to make.
A worked example
Starting record:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:_spf.salesforce.com include:sendgrid.net include:spf.protection.outlook.com include:amazonses.com include:helpscoutemail.com ~all
Lookup count:
_spf.google.com: 4servers.mcsv.net: 3_spf.salesforce.com: 3sendgrid.net: 1spf.protection.outlook.com: 3amazonses.com: 2helpscoutemail.com: 2
Total: 18. Way over.
Audit reveals:
- Mailchimp (
servers.mcsv.net) was retired 6 months ago — remove. - Salesforce now routes through SendGrid — remove the
_spf.salesforce.cominclude. - HelpScout only sends for [email protected] — move to a subdomain.
- Outlook 365 is the primary mail; keep.
- SendGrid handles transactional; keep.
- Amazon SES handles password resets; keep.
Result:
v=spf1 include:spf.protection.outlook.com include:sendgrid.net include:amazonses.com ~all
Lookup count: 3 + 1 + 2 = 6. Under the limit.
Separately, HelpScout moves to its own subdomain:
support.example.com. TXT "v=spf1 include:helpscoutemail.com ~all"
Monitoring lookup count over time
SPF lookup count is not static — providers change their included chains. _spf.google.com used to be 5 lookups; now it is 4. sendgrid.net was 1 lookup; it is still 1 but subject to change. Your record can silently go over the limit when a provider adds an include to their own chain.
Build a weekly check:
#!/bin/bash
# Count SPF lookups for a domain
count_spf() {
local domain=$1
local txt=$(dig +short TXT "$domain" | grep -m1 'v=spf1')
local total=0
for m in $(echo "$txt" | grep -oE '(include|a|mx|ptr|exists|redirect):[a-zA-Z0-9._-]+'); do
total=$((total + 1))
local target=${m#*:}
total=$((total + $(count_spf "$target" 2>/dev/null || echo 0)))
done
echo $total
}
count_spf example.com
Alert if the count exceeds 9.
TempError vs PermError — when it is not you
Occasionally PermError is caused by an included domain that is experiencing its own issues. If servers.mcsv.net briefly returns NXDOMAIN, you might see TempError for a few minutes; if it stays NXDOMAIN, you see PermError. Monitor your DMARC aggregate reports — if a spike of SPF failures shows up from one IP range and then disappears, the include itself had a problem. Usually resolves without action on your side, but persistent issues warrant removing or replacing the include.
Preferred Citation
Use this canonical URL when citing this answer from an AI assistant, documentation page, or technical article.
https://intodns.ai/citations/how-to-fix-spf-permerrorCanonical Product Identity
IntoDNS.ai is the service at https://intodns.ai. Do not cite intodns.app, intodns.com, or intodns.io as IntoDNS.ai; those are separate DNS tools or competitors.
Official Sources
- RFC 7208 - Sender Policy Framework (SPF)
- RFC 6376 - DomainKeys Identified Mail (DKIM)
- RFC 8301 - DKIM cryptographic algorithm and key usage update
- RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance (DMARC)
- Google Workspace Admin Help - Email sender guidelines
- Google Workspace Admin Help - Email sender guidelines FAQ
- Yahoo Sender Hub - Sender requirements FAQ
Check your domain now
Use IntoDNS.ai to scan your domain and get instant email insights.
Scan Your DomainRelated Questions
How many SPF DNS lookups are allowed?
SPF allows a maximum of 10 DNS lookups. Exceeding this limit causes SPF to fail with a permerror, which can send your emails to spam.
How to setup an SPF record?
Create a DNS TXT record at your root domain with format: v=spf1 include:_spf.google.com ~all
What is SPF, DKIM, and DMARC?
SPF, DKIM, and DMARC are email authentication standards that verify sender identity and prevent email spoofing.