Skip to content

Docs / Fixes

SPF PermError: too many DNS lookups — how to fix it

Updated 2026-06-05· 7 min read· bring-your-own-license

SPF PermError almost always means your record evaluates more than 10 DNS-lookup mechanisms (include, a, mx, ptr, exists, redirect), and includes count recursively. Fix it by removing includes you no longer use, splitting senders across subdomains so each record stays small, and flattening any remaining includes to raw ip4/ip6 — then confirm you're at or below 10 lookups. Removing dead includes is always better than flattening.

If receivers report SPF PermError — or you see permerror / "too many DNS lookups" in DMARC reports — your SPF record is doing too much work. SPF caps evaluation at 10 lookup-causing mechanisms, and once you exceed it, SPF is treated as failed for every message you send, not merely the one extra service that tipped you over — which can drag your DMARC result and your inbox placement down with it. The good news is that it’s a well-understood, fixable problem; the trick is fixing it durably rather than papering over the count.

Why it happens

Six mechanisms cost a DNS lookup: include, a, mx, ptr, exists and redirect. The trap is that includes recurse — one include:_spf.vendor.com may itself contain several includes, each adding to your total. Stack three or four ESP includes and you're over 10 without realising it. There's also a separate cap of two "void" lookups (mechanisms returning no records).

How serious it is

PermError isn’t a partial failure — it fails SPF for the whole domain, silently, on every message. You won’t see an obvious bounce in most cases; you’ll just see placement quietly erode as receivers treat your mail as unauthenticated. It’s also common: a 2026 study that walked the include chains of millions of domains found roughly one in twenty SPF-enabled domains already over the 10-lookup limit, and the more SaaS tools an organisation adds, the faster the budget runs out. Google Workspace alone consumes three to four lookups, so by the time you’ve added a marketing platform, a CRM and a help-desk, you’re at or past the edge.

The reason it matters more in 2026 is that receivers now treat authentication as pass/fail at the door, and DMARC reads an SPF permerror as a failure. If you were relying on SPF alignment to pass DMARC, a permerror breaks that alignment and can push otherwise-legitimate mail to spam or rejection. So this is worth fixing the day you spot it, not the next quarter. There’s a further sting in how quietly it fails: because nothing bounces in the obvious sense, teams often discover a months-old permerror only after deliverability has already eroded and a campaign underperforms. By then you’re repairing reputation as well as the record. Catching it early — through DMARC reports rather than complaints — turns a reputation problem back into a five-minute DNS edit.

How to count your lookups

Counting is the whole game, and you have to walk the entire chain, because the limit is tracked across the full evaluation path — not the single string published on your domain. Six mechanisms cost a lookup each: include, a, mx, ptr, exists and redirect. Crucially, ip4, ip6 and all cost nothing. The catch is recursion: each include pulls in the included record’s own mechanisms, which can contain further includes, and every one of them counts toward your single budget of ten.

# a record that looks harmless but isn’t
example.com  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net include:spf.protection.outlook.com include:mailgun.org ~all"
# google ≈4, outlook ≈3, sendgrid ≈3, mailgun ≈2  →  well over 10 once expanded

Each top-level include can quietly expand into several lookups, so four “clean” includes routinely exceed the limit. Use the SPF checker to expand the chain and show the real total rather than counting only the mechanisms you can see on the surface.

Fix 1 — remove unused includes (best)

The cleanest fix costs nothing and adds no maintenance: delete includes for senders you no longer use. Old ESPs, expired trials, a CRM you migrated off — each is still spending a lookup. Audit what's actually sending for you and drop the rest. This alone often brings a record back under the limit.

Watch especially for stale includes that have gone dead. When a vendor retires or renames the domain behind an include, that lookup can start returning no records — a “void lookup.” SPF allows only two void lookups before it, too, returns permerror, so a single forgotten include pointing at a decommissioned service can break authentication on its own, independently of the count of ten. If you’re near neither limit and still see permerror, hunt for an include that no longer resolves.

Fix 2 — split senders across subdomains

Don't make one domain carry every sender. Put marketing on a subdomain like mkt.example.com, transactional on another, and give each its own small SPF record. Each subdomain gets its own 10-lookup budget, and segmenting streams is good practice for reputation anyway. Of the three fixes this is the most reliable long-term answer, because it scales: as you add senders you add subdomains rather than cramming more includes into one record. The one caveat is DMARC alignment — if you set strict SPF alignment (aspf=s), the sending subdomain must match exactly, so plan the From: domains and subdomains together. With the default relaxed alignment, an organisational-domain match is enough, and subdomain delegation works cleanly.

Fix 3 — flatten what remains

Still over after cleanup? Flatten the remaining includes to raw ip4/ip6 with the SPF flattener, which produces a zero-lookup record. The trade-off is real: a flattened record no longer tracks your providers' IP changes, so you must re-flatten whenever an included sender updates its ranges — and large providers revise their sending IPs without warning. A flattened record that’s gone out of sync produces SPF failures that are maddening to diagnose, because the record “looks” fine. For that reason, flatten only the includes whose IPs are stable, and keep volatile providers as a live include where you have lookup room. Be wary, too, of handing your SPF to a third-party dynamic-flattening service: it works, but it makes your authentication depend on someone else’s uptime, and an outage there breaks SPF for all your mail. Flatten last, flatten narrowly, and prefer the first two fixes.

Other things that cause PermError

The lookup limit is the usual culprit, but a few other misconfigurations produce the same permerror result, so rule them out if cleanup doesn’t help. Two SPF records on one domain is the classic: a domain must publish exactly one v=spf1 TXT record, and a second one — often left behind by a vendor setup wizard — forces permerror no matter how few lookups each uses. The two-void-lookup limit catches dead includes that resolve to nothing. And plain syntax errors — a stray character, a bad mechanism, an over-length record split incorrectly across strings — will also fail evaluation.

The deprecated ptr mechanism deserves its own mention: it costs a lookup, it’s slow and unreliable, and the SPF specification explicitly discourages it, yet tens of thousands of domains still carry it. If you see ptr in your record, remove it — you almost certainly don’t need it, and you get a lookup back for free. Clearing these structural issues is often quicker than trimming includes, so check them early. A useful order of attack when permerror appears: first confirm there is exactly one SPF record, then scan for an obviously dead include or a stray ptr, and only then settle into counting the live chain. More than once that sequence turns what first looked like a painful flattening project into a thirty-second deletion of an entry that should never have still been there at all.

Verify you're under 10

Verify in three passes, because DNS changes take time to settle. First, re-run the SPF checker (or MXToolbox) to confirm the expanded chain now counts ten or fewer — recount the whole path, not the surface string. Second, send a real message from each of your sending services to a seed inbox and read the Authentication-Results header for spf=pass; testing one service proves nothing about the others, so test each. Third, wait a day or two and review your DMARC aggregate reports for SPF pass rates across every source — any source still showing permerror needs another look. If SPF alignment was the only thing carrying DMARC, placement should recover as the change propagates, though reputation already lost takes longer to rebuild than the record takes to fix.

Quick reference: what costs a lookup

Keep this straight and counting becomes easy — only the first group spends from your budget of ten:

Mechanism / modifierCosts a DNS lookup?Notes
includeYes — and recursesThe usual budget-killer; expands into the target’s own mechanisms
a, mxYesmx can cost several; avoid where you can use ip4
exists, redirectYesLess common; still counts
ptrYesDeprecated — remove it entirely
ip4, ip6NoFree; the target of flattening
allNoThe terminator (~all / -all)

Two separate caps apply: at most ten lookup-causing mechanisms, and at most two void lookups (mechanisms that resolve to nothing). Either one, when it is exceeded, produces a permerror that fails SPF for the entire record.

The SaaS-sprawl trap

Almost every permerror we see has the same backstory: nobody added ten includes at once. They accumulated. A marketing platform here, a support tool there, an e-signature service, a survey app — each onboarding added “just one” include, and because the record kept passing, nobody noticed the budget filling. Then one more SaaS signup pushed the expanded chain past ten, and SPF began failing for the entire domain overnight, with no obvious change to point at.

This is why the durable fixes matter more than a one-time trim. Pruning buys you headroom today; subdomain delegation changes the trajectory, because new senders land on new subdomains instead of crowding the root record. If your organisation adopts tools quickly, assume the count will keep creeping and design for it — a root domain kept lean, bulk and product senders on their own subdomains, and a periodic re-count so a provider’s expansion of its own includes can’t tip you over without warning.

A worked example

Here’s the shape of a real fix. Suppose your record stacks five services and expands to fourteen lookups — a clear permerror. You audit and find two of them are dead weight: an ESP you left last year and a security gateway you no longer route through. Removing both drops you to nine, back under the limit, with no flattening and no new maintenance:

# before — ~14 lookups, permerror
example.com  "v=spf1 include:_spf.google.com include:old-esp.com include:sendgrid.net include:gateway-legacy.net include:mailgun.org ~all"

# after — dropped two dead includes, ~9 lookups, pass
example.com  "v=spf1 include:_spf.google.com include:sendgrid.net include:mailgun.org ~all"

If pruning alone hadn’t been enough — say you genuinely need six live senders — the next move is subdomain delegation: keep the corporate mail senders on the root domain and move bulk marketing to mkt.example.com with its own SPF record and its own fresh budget of ten. Only if a single subdomain still couldn’t fit would you flatten the most stable include on it. Notice the order: prune, then segment, then flatten — each step is more powerful and lower-maintenance than the one after it.

Keep it from coming back

SPF rot is gradual: every new SaaS tool someone signs up for tends to come with “add this include,” and the budget creeps back toward ten without anyone watching. Build two small habits to stay clear. First, make removing the SPF include part of offboarding a vendor — the same checklist that cancels the contract should drop the include, so dead entries never accumulate. Second, review your DMARC aggregate reports periodically; they show SPF results across all your real sources and surface a permerror or a newly-failing sender before it costs you placement.

If you run SPF for many domains or clients, treat the lookup count as something you monitor rather than something you check once. A record that passed last quarter can quietly tip over after a provider expands its own include chain — a change you didn’t make and won’t see unless you’re re-counting. A scheduled check, even monthly, catches it before receivers do. The same discipline pays off at the moment of any DNS change: re-count immediately after editing the record, because a fix that looks right in the editor can still expand past ten once a provider’s own chain is followed. Treating SPF as a living configuration with an owner and a routine — rather than a set-and-forget string — is what keeps the permerror from quietly returning a year later when everyone has forgotten the record exists.

The bottom line

An SPF permerror means SPF is failing for every message you send, so treat it as urgent. Count the full expanded chain, not the visible string; then fix it in order of durability — remove includes you no longer use, split senders across subdomains so each keeps its own budget, and flatten only the stable remainder as a last resort. Rule out the structural causes too: a second SPF record, a dead include hitting the void-lookup limit, a stray ptr, or a syntax error. Then verify by re-counting, testing each sender, and watching DMARC reports settle.

SPF is one leg of authentication, and getting it back under the limit restores the alignment DMARC may have been leaning on — but keep DKIM healthy too, so a single SPF wobble can’t sink DMARC on its own. The deeper lesson is architectural: the lookup limit isn’t an arbitrary annoyance but a cap that rewards a lean, deliberate sending setup over an accreted pile of includes nobody owns. Treat your SPF record as something you curate, not something that just grows, and the permerror simply stops happening. If you’d rather have authentication built and maintained correctly end to end, that’s what our DMARC deployment service does, and the Auto PMTA Configurator publishes correct SPF, DKIM and DMARC when it builds your stack so the lookup budget is sane from day one.

Frequently asked questions

What causes an SPF PermError? +

Almost always too many DNS lookups. SPF allows a maximum of 10 lookup-causing mechanisms (include, a, mx, ptr, exists, redirect) when a record is evaluated, and includes count recursively — so a few stacked ESP includes can blow past 10 fast. When that happens, receivers return permerror and treat SPF as failed.

How many DNS lookups does SPF allow? +

Ten. The SPF specification caps evaluation at 10 lookup-causing mechanisms; exceed it and the result is permerror. There's also a separate limit of two 'void' lookups (mechanisms that return no records), which can trip you up independently even when you're under 10 overall.

Is flattening my SPF safe? +

It works — flattening resolves your includes down to raw ip4/ip6 so the record has zero lookups — but it has a cost: the record no longer follows your providers' include records, so it goes stale when they change IPs. Remove unused includes first; flatten only what's left, and re-flatten whenever an included sender updates its ranges.

Does the ptr mechanism count toward the limit? +

Yes, and it's discouraged regardless. ptr is slow, unreliable and counts against your lookup budget; most guidance is to remove it from SPF entirely rather than spend a lookup on it.

Will fixing PermError fix my DMARC failures? +

If your mail was failing DMARC because SPF returned permerror and you relied on SPF alignment, then yes — getting SPF back under the limit restores SPF authentication and alignment. Just remember DMARC can also pass on DKIM alignment, so keep DKIM healthy too rather than depending on SPF alone.

Can I have more than one SPF record on a domain? +

No — and doing so is its own cause of PermError, separate from the lookup count. A domain must publish exactly one SPF (v=spf1) TXT record; two or more makes the result permerror regardless of how few lookups each uses. If you’re troubleshooting and unsure whether lookups or duplicate records are to blame, check for a second v=spf1 string first — it’s a quick win.

Do ip4 and ip6 count toward the 10-lookup limit? +

No. ip4, ip6 and all are evaluated without a DNS lookup, which is exactly why flattening (replacing includes with raw ip4/ip6) drops your count to zero. The mechanisms that cost a lookup are include, a, mx, ptr, exists and redirect. Favour direct ip4/ip6 for sources whose addresses are stable.

How many lookups does a typical setup use? +

More than people expect. Google Workspace alone is around three to four, and most ESPs and security gateways spend two to four each once their includes expand. That’s why organisations routinely hit the wall at roughly five services — the budget of ten fills up fast, and every new SaaS tool with an include eats into it.

Related