A permerror result means the receiving server stopped evaluating your SPF record and gave up. Two causes account for almost all of them: your record needs more than ten DNS lookups to resolve, or your domain publishes more than one SPF record. Both are defined as permanent errors in the standard, so SPF does not pass, does not fail, and simply produces nothing usable.
The practical effect is that every message you send is unauthenticated on the SPF side, which is enough on its own to get you rejected by some providers.
What does permerror actually mean?
SPF is a recursive lookup. Your record lists mechanisms, some of which point at other records, which point at others. A receiving server has to resolve the whole tree before it can decide whether the sending server was authorised. To stop that becoming a denial-of-service amplifier, RFC 7208 caps it. Section 4.6.4 is unambiguous about the cap and about what happens when you cross it:
SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS.
RFC 7208, section 4.6.4
Cross that line and the standard requires the receiver to return permerror. Section 4.5 sets the other trap: "If the resultant record set includes more than one record, check_host() produces the permerror result." Two SPF records on a domain is not additive. It is invalid.
Neither of these is a sending failure, which is why it is easy to miss. Your mail leaves. Your relay accepts it. The damage happens at the receiving end, and only shows up as an authentication result buried in the message headers. If your problem is that mail does not leave at all, you want your host blocks the SMTP port or 535 username and password not accepted instead. If it leaves and vanishes, the sign-in email never arrives traces it. This page is about a record that is syntactically present and functionally void.
The reason self-hosters land here is cumulative. Google Workspace is already in the record. Then a transactional provider gets added for the support centre, then a marketing tool, then an invoicing service. Each hands you an include:, and none mentions that you have a budget of ten.
How do you count your own lookups?
Start by reading the record itself:
dig +short TXT yourdomain.com | grep spf1
Then check you only have one of them. This should print 1:
dig +short TXT yourdomain.com | grep -c 'v=spf1'
Anything higher and you have found your problem already. A 0 means SPF is not published at all.
Now walk the tree. Every include: in your record is one lookup, and whatever that record contains costs more. Resolve each one:
dig +short TXT _spf.google.com
dig +short TXT spf.protection.outlook.com
Google's own record is itself a set of includes, so it costs several lookups rather than one. Add them up by hand, or run the record through one of the free SPF validators, which do the recursion and print a running total. Count against this table, not intuition.
| Term | Does it cost a lookup? |
|---|---|
include: | Yes, one, plus everything inside it |
a | Yes |
mx | Yes, and each MX may not resolve more than ten address records |
ptr | Yes, and the standard discourages it entirely |
exists: | Yes |
redirect= | Yes |
ip4: and ip6: | No |
all | No |
exp= | No |
There is a third limit almost nobody knows about. Terms that resolve to nothing, called void lookups, should be limited to two. An include: pointing at a service you cancelled years ago, whose record has since been withdrawn, counts against that separately.
How do you get back under ten?
In this order, because the first two are free and the third has a real cost.
- Delete what you no longer send from. Most over-limit records contain at least one include for a service that was cancelled. Every removal is a lookup back, with no downside at all.
- Replace an include with the addresses it resolves to, but only where the provider publishes a stable, documented range.
ip4:andip6:mechanisms cost nothing against the limit. The catch is that you now own the maintenance: if the provider changes an address and you do not notice, your mail silently starts failing SPF. - Do not use an automated flattening service unless you understand the trade. These rewrite your record into raw addresses and keep it updated, which does solve the count. It also puts a third party in the path of your mail authentication.
- Split senders onto subdomains. Send your support centre's notifications from
notifications.yourdomain.comand your marketing frommail.yourdomain.com. Each subdomain gets its own SPF record and its own budget of ten. This is the cleanest answer and the one that keeps working as you add senders. - Never solve it by adding a second record. That is the other permerror, and it will replace a partly working record with a completely broken one.
One payment, no subscription, unlimited products.
How do you tell it worked?
Do not judge by whether the mail arrived. Read the authentication result the receiving server wrote into the headers. Send a message to an account you control at each provider your users are actually on, open the original message rather than the rendered one, and look for the Authentication-Results header. You want spf=pass, and dkim=pass and dmarc=pass alongside it.
If you still see spf=permerror, DNS caching is the usual reason for a fix appearing not to have landed. Check what the world is being served rather than what you saved:
dig +short TXT yourdomain.com @8.8.8.8 | grep spf1
Query a resolver you do not control, wait out the record's own TTL, and test again before changing anything else.
Two symptoms worth separating. permerror means your record is invalid. A hard fail, written -all in your record, means the record is valid and this particular server is not on the list, which is a completely different fix: add the sender, do not touch the limit. And a temperror is a DNS timeout rather than a record problem, so retrying is a reasonable response to that one.
Why this matters more than it used to
An unauthenticated message used to be a deliverability risk. Since February 2024 it is a rejection at Gmail, whose sender requirements now oblige every sender to set up SPF or DKIM, with both required above 5,000 messages a day. A permerror means SPF is not doing its half of that, and if DKIM is not carrying you, the message is refused outright with 550 5.7.26.
Server Fault's most-viewed question on the two-record version of this, "Multiple TXT fields for same subdomain", stands at 130,840 views and a score of 98, checked through the Stack Exchange API on 23 August 2026. It is not an obscure mistake.
One less sender in the record
A closing note on scope. Docket's free edition sends no email, so it needs no place in your SPF record at all and cannot contribute to the count. The paid tiers add notifications, and they go out through whichever transactional provider you already use, which for most people is an include that is in the record anyway. That is one sender fewer to budget for. It is not an exemption from the limit, and if you are already at ten, adding anything at all will break it. SMTP for self-hosted tools covers what SPF, DKIM and DMARC each do before you go rearranging them.
Frequently asked questions
Does the ten-lookup limit count the SPF record itself?
No. The initial lookup that fetches your domain's own SPF record is not counted. The budget of ten applies to the terms inside it that trigger further DNS queries, which are include, a, mx, ptr, exists and the redirect modifier. Mechanisms that carry an address literal, ip4 and ip6, cost nothing.
Can I just have two SPF records, one for each provider?
No, and this is the single most common way people make things worse. The standard says a domain publishing more than one SPF record produces a permerror, which is a harder failure than being over the lookup limit with one record. Merge the mechanisms from both into a single record with one v=spf1 and one all at the end.
Is SPF flattening safe?
It works, and it moves a risk rather than removing one. Replacing includes with literal addresses gets you under the limit, but those addresses are now a snapshot. When a provider changes its sending infrastructure, your record is silently wrong and your mail silently stops passing SPF. If you flatten, either automate the refresh or diary a review.
Will DKIM save me if SPF is in permerror?
Often, but not always, and it depends on the receiver. Gmail's baseline requirement is SPF or DKIM, so a valid DKIM signature can carry a message that fails SPF. DMARC also passes on either check aligning. Above 5,000 messages a day to Gmail, both are required, and relying on one leaves you no margin.
How long after fixing the record will mail start passing?
As soon as the old record expires from the caches serving your recipients, which is governed by the TTL on the record you replaced, not by how quickly your DNS provider saved it. Query a public resolver you do not control to see what the rest of the world is being handed, and re-test with a real message after the TTL has elapsed.