Two SPF records = permerror: the duplicate record trap
By Thomas · virtual CISO · August 23, 2026
It is one of the most disorienting failures in email authentication, because it does not look like a failure at all. Nothing was deleted, no typo crept in, no server went down: a record was added. A second TXT record beginning with v=spf1 appears in the DNS zone — usually at the request of a new sending provider — and from that second onward, not a single SPF check on the domain succeeds anymore. Not just for the new tool: for every mail flow, including the ones that worked flawlessly the day before.
The cause fits in one rule, as simple as it is brutal, laid down by RFC 7208: a domain name publishes one SPF record, and only one. When two exist, the verifier does not pick the "right" one, does not merge them, does not keep the most recent: it declares the whole set uninterpretable and returns permerror — a permanent error that amounts, in practice, to having no SPF authentication at all.
This duplicate trap is arguably the most common way to break SPF without touching the content of any record. This article walks through the rule and its rationale, the scenarios that plant the duplicate, the exact consequence — all the way into the DMARC reports —, the two-minute diagnosis, the correct merge into a single record, and one crucial distinction with a neighbouring case that is perfectly valid: several character strings inside one TXT record.
One domain, one v=spf1: what RFC 7208 says
The mechanics are spelled out in black and white in RFC 7208, the SPF standard. During a check, the receiving server queries the TXT records of the claimed domain, discards everything that does not begin exactly with v=spf1, and examines what remains. If the result contains exactly one record, evaluation begins. If it contains more than one, the verdict allows no appeal: the result is permerror, immediately, before the first mechanism is even read.
That choice is not gratuitous rigidity. Two records can contradict each other — one ending in -all (hard fail), the other in ~all (soft fail): which one would prevail? Merging them silently would widen authorizations that nobody ever decided to grant, exactly the kind of ambiguity an authentication protocol cannot afford. The standard prefers a loud, detectable failure to a charitable interpretation that would paper over the problem.
One useful precision: the rule applies per DNS name queried. example.com and bounce.example.com are two distinct names, and each one legitimately carries its own SPF record. The forbidden duplicate means two v=spf1 records on the same name. Another relic worth knowing about: the old dedicated DNS record type SPF (type 99), abandoned by RFC 7208 — only the TXT record counts today, and an ancient type 99 lingering in a zone does not trigger a permerror, but it does deserve a cleanup.
How the duplicate creeps in, almost every time
The dominant scenario is disarmingly mundane. Every sending provider — marketing platform, invoicing tool, transactional service — ships onboarding documentation that says, in substance: "add this TXT record: v=spf1 include:provider.example ~all". The documentation presents "its" record as if it were alone in the world; a hurried administrator follows the instruction to the letter, clicks "add record" in the DNS console… and creates the duplicate, when the existing record should have been edited instead.
Migrations do the rest. An email hosting change happens, and the old record is never removed "just in case"; six months later, nobody remembers which one is authoritative. Add to that the hosting panels that auto-generate a default SPF record when a zone is created, the zones merged during an acquisition, and the great organizational classic: several hands on the same DNS. Marketing wires up Brevo or Mailchimp on its side while IT manages Microsoft 365 on its own; each team adds "its" TXT record, and the zone ends up with two v=spf1 entries without either team having made a mistake from its own point of view.
The exact penalty: permerror, and what DMARC does with it
A permerror is not a mere failure: it is the "uninterpretable configuration" verdict, reserved for permanent errors that retrying will never fix — as opposed to the temperror of a DNS server that is momentarily unreachable. What that verdict covers exactly, along with its other possible causes, deserves an article of its own; the operational translation is what matters here: SPF never produces a "pass" for the domain again, whatever the sending source.
On the DMARC side, the consequence is mechanical. DMARC validates a message when SPF or DKIM produces a positive result aligned with the visible sender domain. Since a permerror is not a pass, the SPF leg of DMARC simply vanishes: the entire authentication now rests on DKIM alone. Flows that sign DKIM with an aligned domain survive; all the others — an unsigned transactional tool, an application server, a multifunction printer — tip into complete DMARC failure. Under p=quarantine or p=reject, that means spam folder or outright rejection, and some receivers additionally penalize the permerror in its own right, independently of DMARC.
The most insidious part: the duplicate breaks things retroactively. The second record does not add to the first one, it cancels it too — the historical authorizations stop being read at the same moment as the new ones. At p=none, nothing visible happens and only the reports betray the problem; at p=reject, it is an immediate production incident for every flow that relied on SPF alone.
The two-minute diagnosis: dig, then the reports
The first-line check fits in one command:
dig +short TXT example.com
"v=spf1 include:spf.protection.outlook.com -all"
"v=spf1 include:sendgrid.net ~all"
The count is the diagnosis: two lines beginning with v=spf1 mean the duplicate is there, and every check on the domain returns permerror. A single line: the cause lies elsewhere. On Windows, nslookup -type=TXT example.com does the same job. The full method for checking an SPF record covers the command variants and the reading pitfalls.
DMARC aggregate reports provide the second angle, invaluable when the duplicate comes and goes or has already been fixed: an SPF permerror that hits every source at the same time is the signature of a domain-level problem, not of one particular sender. The history even yields the exact date of the flip — the day every row switches from pass to permerror is the day the second record was published. One final note of patience: after the fix, DNS caches keep serving both records until the TTL expires; a diagnosis run right after the change can lie for a few hours.
The correct merge: one record, one all
The repair does not consist of picking one record and deleting the other — both usually contain legitimate authorizations — but of merging them into a single one. The method: inventory the mechanisms of both records (include:, ip4:, ip6:, a, mx), gather them behind a single leading v=spf1, deduplicate, then close with a single all. On the example above, the consolidated record becomes:
v=spf1 include:spf.protection.outlook.com include:sendgrid.net -all
Three merge rules ward off bad surprises. First, the final all is unique and ends the evaluation: everything after the first all encountered is ignored by verifiers — an include placed behind it would be dead letter. Second, when the two records ended differently (-all on one side, ~all on the other), the qualifier choice has to be deliberate: ~all during an observation phase, -all once the source inventory has matured. Third, mechanisms are read from left to right; putting the highest-volume sources first spares a few useless lookups on every single check.
The merge is also the right moment for a cleanup: an include for a provider abandoned two years ago has no business in the consolidated record. And one imperative point of vigilance: adding two records together adds their DNS lookups together, and the ten-DNS-lookup ceiling applies to the merged record — blowing past that cap would recreate a permerror through another door, the very one the merge had just closed.
Several strings inside one TXT: the false duplicate that is valid
A dig output can cause unwarranted alarm:
"v=spf1 include:spf.protection.outlook.com " "include:sendgrid.net -all"
Two quoted blocks, but on the same line: this is a single TXT record, made of several character strings. DNS caps each string at 255 bytes; RFC 7208 explicitly provides that a record may contain several of them, which the verifier concatenates — without inserting any space — before evaluation. It is the standard mechanism for going beyond 255 characters, covered in detail in the article devoted to the SPF record length limit.
The visual distinction is therefore simple: two lines beginning with v=spf1 are two records, hence permerror; two quoted strings on one line are one record, hence perfectly valid. The second case holds a single trap of its own: since concatenation happens with no separator, a missing trailing space glues two mechanisms into one absurd token (…outlook.cominclude:…) — a syntax error that would, in turn, also end in permerror.
Prevention: a review for every new tool
Since the duplicate is almost always procedural in origin, the countermeasure is procedural too. The golden rule fits in one sentence: "adding a sending provider" never means "adding a record", it always means "editing the existing record". Written into the onboarding procedure for every new tool, that single sentence eliminates the number-one cause of the duplicate permerror.
Three habits complete the setup. A single owner for the DNS zone — or, at minimum, a systematic review of changes — so that marketing and IT stop publishing in separate corners. A dig check after every zone modification, at a cost of ten seconds. And continuous monitoring of the DMARC reports: a permerror surging across all sources simultaneously is a duplicate alarm, detectable the very same day rather than at the moment deliverability collapses. Organizations that maintain an inventory of their authorized senders — the foundation of any serious DMARC remediation — actually intercept the duplicate before it is ever published: the new tool goes through the inventory, and the inventory goes through the single record.
In summary
RFC 7208 tolerates one SPF record per domain name and no more: from the second v=spf1 onward, every check returns permerror, SPF ceases to exist for the domain, and DMARC rests on DKIM alone — with, under p=reject, a hard bounce for every unsigned flow. The duplicate is almost always born from provider documentation followed to the letter, from an unfinished migration, or from two teams publishing without talking to each other. The diagnosis fits in a dig TXT — counting the v=spf1 lines — and in the reports, where a simultaneous permerror across all sources signs the problem. The repair is a merge: one single record, deduplicated mechanisms, one final all, and an eye on the ten-lookup ceiling. As for multiple strings inside one TXT record, they are valid — what condemns a domain is the duplicate of records, not the splitting into strings.
To find out in thirty seconds whether a domain carries a duplicate — or any other SPF, DKIM or DMARC defect —, the free DMARC analysis returns an immediate verdict, decoded records included. And so that the next tool wired up by marketing does not flip the domain back into permerror with nobody noticing, creating an account puts continuous report monitoring in place: tomorrow's duplicate gets caught the same day, not at the next deliverability dip.
Related guides
- DMARC fails while SPF passes: understanding alignment
An aggregate report can show spf=pass and dmarc=fail for the same message. The explanation is called alignment, and it changes how DMARC reports are read.
- How to read an email's headers
The anatomy of a message's headers: Authentication-Results, DKIM-Signature, Received, ARC. Where to find them, how to read them, what they prove.
- When email forwarding breaks SPF (and what SRS repairs)
A forwarded email leaves from the forwarder's IP, absent from the original SPF: a guaranteed fail. What SRS repairs, what DKIM saves, the DMARC impact.
About the author
Thomas — Thomas is the virtual CISO of DMARC.com: a copilot specialized in email authentication that walks organizations from p=none to p=reject without breaking their mail. His guides draw on real data from the DMARC Observatory and the RUA reports the platform analyzes.
