DMARC permerror vs temperror: one fixes itself, the other kills your deliverability
You’re reading your DMARC aggregate report and something’s wrong with SPF. The result column doesn’t say pass or fail — it says permerror or temperror. Your DMARC enforcement policy is set to p=quarantine, and you need to know whether this is a crisis or background noise.
The answer depends entirely on which error you’re looking at.
The short version
temperror means the receiving server couldn’t evaluate your SPF record due to a transient DNS problem — timeout, SERVFAIL, a DNS resolver that briefly went unresponsive. Receiving servers are supposed to treat this like a soft fail under most policies. It usually disappears on its own.
permerror means the receiving server tried to evaluate your SPF record and found something fundamentally broken — a structural defect it cannot work around. It won’t fix itself. Every message from the affected sender keeps failing until you change the record.
If you’re seeing permerror in a significant fraction of your report rows, stop reading and go fix your SPF. The rest of this post will explain exactly what to look for.
Not sure if anyone’s forging your domain while you debug this? Check your domain at DMARC Guardian’s free domain checker — it takes 30 seconds.
What the RFCs actually say
Both error types are defined in RFC 7208, the SPF specification.
temperror (§2.6.6): A transient error occurred during evaluation. The typical cause is a DNS lookup that failed due to a network problem, DNS server downtime, or a SERVFAIL response from an authoritative server. The record itself may be perfectly valid — the evaluator just couldn’t reach the DNS infrastructure needed to finish the check.
permerror (§2.6.7): A permanent error occurred during evaluation. The record has a structural problem that makes evaluation impossible regardless of DNS health. Examples include: hitting the 10-lookup limit, encountering multiple SPF records on the same name, or finding a syntax error the evaluator cannot parse.
The distinction matters for DMARC policy enforcement. When a receiver gets temperror, it may treat the message more leniently — RFC 7489 §5.6.1 permits receivers to effectively accept the message rather than defer or fail it for that evaluation. When a receiver gets permerror, it’s treated as a hard SPF failure, which feeds directly into your DMARC policy.
Where these errors appear in aggregate report XML
DMARC aggregate reports encode authentication results inside <record> elements. You’ll find SPF results here:
<auth_results>
<spf>
<domain>yourdomain.com</domain>
<result>permerror</result>
</spf>
</auth_results>
If the result is permerror, the row’s DMARC disposition depends on whether DKIM passed and aligned. If DKIM also failed, the message failed DMARC entirely. If DKIM passed with alignment, DMARC still passes — but SPF is a broken path for that sender.
DMARC Guardian’s Issues tab filters these rows automatically. Look for SPF result = permerror grouped by source IP to see which senders are affected.
The most common permerror traps
1. The 10-lookup limit
SPF evaluation can trigger at most 10 DNS lookups — across all include:, a, mx, ptr, and exists mechanisms, recursively. Hit lookup 11 and the evaluator returns permerror.
This is the single most common cause of permerror in production. See SPF permerror: why adding one SaaS tool breaks your email authentication for the complete breakdown of how to count your lookups and how to fix it with SPF flattening. No point reproducing it here.
2. Two SPF records on the same name
This one silently breaks authentication for the entire domain and is surprisingly easy to do. If your DNS zone has two TXT records at the same name that both start with v=spf1, evaluating servers return permerror immediately, per RFC 7208 §3.2.
yourdomain.com TXT "v=spf1 include:_spf.google.com ~all"
yourdomain.com TXT "v=spf1 include:sendgrid.net ~all"
This is the result of well-meaning additions. Someone already had an SPF record. A developer or IT admin added a new service and published a second SPF record instead of editing the existing one. Now both records are broken — not just the duplicate.
The fix: Merge them into a single record:
yourdomain.com TXT "v=spf1 include:_spf.google.com include:sendgrid.net ~all"
Check for this with:
dig TXT yourdomain.com +short | grep "v=spf1"
If you get two lines back, you have the problem.
3. Syntax errors
Less common but still real: a typo in a mechanism token, a malformed IP range (ip4: with an invalid CIDR), or an unknown mechanism that the evaluator doesn’t recognize. These produce permerror immediately during parsing.
v=spf1 include:_spf.google.com ip4:10.0.0/24 ~all # invalid CIDR — missing bits
v=spf1 includes:_spf.google.com ~all # "includes" is not a mechanism
Run your record through a parser before publishing changes. A quick dig TXT yourdomain.com +short and a visual pass catches most of these.
When temperror becomes a real problem
A single temperror is noise. Every DNS infrastructure has occasional hiccups. The mail receiver will typically retry, and the retry usually succeeds.
What you want to watch is patterns:
temperrorappearing across many report senders (Google, Yahoo, Microsoft all returning it) → your authoritative DNS server had a period of downtime, or your DNS provider had an incidenttemperrorconcentrated at a specific subdomain used in your SPF chain → that third-party provider has flaky DNS on their SPF subdomain (_spf.provider.comresolving unreliably)temperrorrecurring regularly, week over week → your DNS hosting is unreliable
For the first case, review your DNS provider’s status history. If you’re on a free or budget DNS tier and seeing recurring temperror that’s measurably impacting your pass rate, it’s worth evaluating a higher-reliability DNS host. Major providers like Cloudflare, AWS Route 53, and Google Cloud DNS publish historical uptime metrics and generally have fewer transient failures than smaller providers.
For the third-party case, you can’t fix their DNS — but you can reduce your dependency on it. SPF flattening resolves include: chains down to IP addresses, removing recursive DNS lookups for those providers. If a provider’s DNS goes down, your flattened record (which has their IPs as ip4: ranges) still evaluates cleanly. This is a secondary benefit of flattening beyond the lookup-count problem.
Which sender is triggering it?
Both permerror and temperror in your aggregate reports are tied to specific source IPs. The workflow for isolating the problem:
- Open your aggregate report for the period in question
- Filter for rows where SPF result is
permerrorortemperror - Note the source IP — this is the server that sent the message
- Map the IP to a service: DMARC Guardian’s IP attribution column does this automatically; otherwise reverse-DNS lookup and cross-reference with your sender list
- For
permerror: that service’s sending path is hitting a broken SPF record — check which domain’s record is malformed - For
temperror: that DNS resolver or that provider’s DNS had a transient problem at that time
The source IP is the critical data point. permerror on traffic from 209.85.x.x (Google Workspace) tells you something very different from permerror on traffic from 149.72.x.x (SendGrid).
The decision tree
Is this permerror or temperror?
├── temperror
│ ├── Isolated incident → monitor, no action needed
│ └── Recurring pattern across multiple reporters
│ ├── DNS provider downtime → review provider reliability
│ └── Third-party SPF DNS flaky → consider SPF flattening
└── permerror
├── Run: dig TXT yourdomain.com +short | grep "v=spf1" | wc -l
│ └── Result is 2 → you have duplicate SPF records → merge immediately
├── Count your DNS lookups (see /blog/spf-too-many-dns-lookups)
│ └── Count ≥ 10 → flatten your SPF record
└── Review syntax → fix the malformed mechanism
Checking your current state
Before making changes, get a clean read of your current SPF record:
# Check for duplicate SPF records
dig TXT yourdomain.com +short | grep "v=spf1"
# Count lookup-triggering mechanisms (rough estimate)
dig TXT yourdomain.com +short | grep -oE '(include|a|mx|exists|ptr):[^[:space:]]+' | wc -l
DMARC Guardian’s DNS tab gives you the same view with the full recursive resolution — it expands every include: and shows the total lookup count including the nested tree, which the dig approach misses.
If permerror is appearing consistently in your reports and you haven’t fixed SPF yet, every day you wait is a day some fraction of your legitimate mail fails DMARC and gets quarantined or rejected. The fix is rarely complex — usually a merge of duplicate records or an SPF flattening job — but it has to be done deliberately or it breaks other senders. Start with the Issues tab in DMARC Guardian: it surfaces which rows are failing and maps each source IP to the sending service responsible, so you know exactly where to look before touching DNS.