HighAuthentication

SPF record contains a syntax error

SPF has a strict grammar: a version tag, then terms separated by single spaces. One malformed term (a stray character, a misspelled mechanism, a comma where a space belongs) can invalidate the record. Some receivers stop at the bad term and evaluate what came before, others return permerror for the whole record, so the same message can be authenticated at one provider and not at another.

Check your own domainSPF checker

What causes this

SPF has a strict grammar: a version tag, then a sequence of mechanisms and modifiers separated by single spaces. A malformed term (a typo in a mechanism name, a stray character, a missing colon) makes the record invalid. Some receivers stop at the bad term, others return permerror for the entire record, so the observable behaviour is inconsistent and hard to debug.

What it breaks

SPF results become unreliable and differ between receivers. Mechanisms after the error may be ignored entirely.

What the receiving server does

This is the failure mode that is hardest to diagnose, because it is inconsistent by design. RFC 7208 defines the grammar but receivers differ in how strictly they enforce recovery from a violation. A message may pass SPF at one large mailbox provider and return permerror at another with no change on your side. If your evidence is a handful of test messages to one provider, a broken record can look healthy.

The mistakes that actually appear in records

Nearly all syntax errors come from a small set of habits carried over from other formats. SPF is space separated, not comma separated, and it has no quoting rules of its own beyond those DNS applies to the TXT string.

badv=spf1 include:_spf.google.com, include:sendgrid.net ~allcommas are not separators: the comma becomes part of the term
badv=spf1 include: _spf.google.com ~allno space is permitted after the colon
badspf1 include:_spf.google.com ~allmissing the v= prefix, so it is not an SPF record at all
goodv=spf1 include:_spf.google.com include:sendgrid.net ~allsingle spaces, one version tag, one trailing all

How to fix it

Correct the invalid term so the record parses cleanly.

  1. Review the flagged term against the SPF grammar.
  2. Check for the usual causes: a space inside an include value, a missing colon after include, a smart quote pasted from a document, or two mechanisms run together.
  3. Republish the corrected record and re-check.

If you send with

Records assembled by copy and paste
Most syntax errors enter through a document or a support ticket, where a text editor has replaced a straight hyphen with an en dash or wrapped a long record across lines. Paste into a plain text editor first and check the characters, particularly around -all and ~all.
DNS panels that split long strings
A TXT record longer than 255 characters must be published as multiple quoted strings which the resolver concatenates. Some panels do this automatically and correctly, others require the quoting to be written by hand and will happily store something that does not reassemble into valid SPF. If the record is long, verify what resolves rather than what you typed.

Confirming the fix worked

  1. Re-run the check above, which evaluates the record as a receiver would rather than reading it as text.
  2. Confirm the record begins exactly v=spf1 with no leading whitespace and no preceding characters.
  3. Check that terms are separated by exactly one space, with no commas and no space after a mechanism colon.
  4. Confirm there is exactly one all term and that it is the last one, since anything after it is unreachable.

Common questions

Are commas allowed in an SPF record?
No. Terms are separated by spaces only. A comma is not a separator and becomes part of whichever term it touches, which usually makes that term invalid.
Does the order of mechanisms matter?
Yes. Evaluation is left to right and stops at the first match, so a match early in the record decides the result. It also matters that all comes last, because it matches everything and makes any later term unreachable.
Is SPF case sensitive?
Mechanism names and the version tag are not case sensitive, so INCLUDE and include behave identically. Domain names are likewise case insensitive. Relying on this is still poor practice, because it makes records harder to read and to diff.
My record is over 255 characters. Is that the problem?
It can be. A single DNS TXT string cannot exceed 255 characters, so longer records must be split into several quoted strings that resolvers join together. Done correctly it is valid; done incorrectly you get a record that looks right in the panel and resolves to something malformed.
Why does the record pass at one provider and fail at another?
Because receivers differ in how they recover from a grammar violation. Some evaluate the terms before the error, others reject the record outright. Inconsistent results across providers are a strong signal that the problem is syntax rather than policy.