A permerror report tells you the record could not be evaluated. It does not tell you why, and there are six distinct causes. Naming the term responsible is the difference between a fix and a guess.
The six
| Cause | How to confirm it |
|---|---|
| Two or more records beginning v=spf1 | dig +short TXT domain | grep -c spf1 returns more than 1. |
| Over the ten-lookup budget | The audit from module 3 exceeds 10. |
| More than two void lookups | The sweep from module 3 finds three or more names returning nothing. |
| An include target with no SPF record | A target resolves, or does not, but has no v=spf1 TXT. |
| Malformed syntax | An unknown mechanism, a bad CIDR, a stray character from an edit. |
| Terms after all | Not an error, and worth catching in the same pass — they are unreachable. |
Check them in this order
Cheapest and most common first. Most permerrors are resolved by the first three checks.
D=example.com # 1. more than one record — instant, and a very common cause dig +short TXT "$D" | grep -c spf1 # 2. walk the tree, counting, and note anything that returns nothing dig +short TXT "$D" | tr -d '"' | grep -o 'v=spf1.*' for t in $(dig +short TXT "$D" | tr -d '"' | tr ' ' ' ' | grep '^include:' | cut -d: -f2-); do printf '%-40s ' "$t" n=$(dig +short TXT "$t" | grep -c spf1) [ "$n" = "0" ] && echo 'VOID / no SPF record <-- cause' || echo "ok ($n record)" done # 3. if mx is present, it costs more than one dig +short MX "$D" | wc -l
The two-record case is worth checking first every time
It is instant, it is invisible in most control panels — which show you records one at a time — and it is what happens when somebody adds a second record for a new platform rather than editing the existing one. A domain can be at permerror for months this way with a perfectly reasonable-looking record on screen.
What to write down
A permerror finding is only actionable if it names the term:
BAD: "acme.com is at permerror"
GOOD: "acme.com: permerror. include:_spf.oldvendor.example (term 4) no
longer has an SPF record — one of three void lookups, over the
two-void limit in RFC 7208 §4.6.4. Remove it; the vendor was
cancelled in 2024. Count after removal: 6 of 10."The second version can be handed to someone else, argued with, and checked after the fact. The first cannot.
After the fix
- Re-run the full audit rather than assuming one removal was enough. Records often have more than one cause.
- Confirm with a real message, not just the record — the record being valid and mail passing are separate claims.
- Note the headroom you ended up with. Landing at 10 of 10 means you will be back.