You paste a long DKIM public key into your DNS provider, save it, and suddenly mail signed with that key fails validation. The record looks right in the dashboard, yet a lookup returns something broken. The culprit is a rule buried in the original DNS specification: a single TXT string can hold at most 255 characters. Longer values must be broken into several quoted strings inside one record, and the way resolvers stitch those pieces back together is where things quietly go wrong. This guide explains the limit, how to split a long value correctly, and the concatenation mistakes that break DKIM and SPF.
Where the 255 limit comes from
RFC 1035 defines the wire format for DNS data. A TXT record's data is made of one or more units called character-strings, and each character-string begins with a single length byte. Because that length byte can count at most 255, no individual string can exceed 255 octets. This is not a provider limitation or a quirk of one resolver; it is baked into the protocol itself. A DKIM key or a long SPF value regularly exceeds 255 characters, so it physically cannot live in one string.
One record, many strings
The limit is on each string, not on the record. A single TXT record may contain multiple character-strings placed one after another, each up to 255 octets, and resolvers concatenate them into one logical value. In zone-file syntax you express this as several quoted strings separated by whitespace, all on the same record.
example.com. IN TXT "first chunk up to 255 chars" "second chunk"
A real DKIM record, which is far too long for one string, is split the same way.
selector._domainkey.example.com. IN TXT (
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA"
"nMoJK1qQ0lFzpF9yAbcDeFgHiJkLmNoPqRsTuVwXyZ0123456789abcdefghij"
"klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZwIDAQAB" )
The parentheses let the record span multiple lines in a zone file; they are not part of the data. Each quoted segment is its own character-string on the wire, and all of them belong to the single TXT record for that name. A resolver or signing library reading this record sees three character-strings, each prefixed by its own length byte, and treats them as one value. There is no architectural limit on how many strings a single TXT record may contain, so even a 2048-bit DKIM key, which runs several hundred base64 characters, fits comfortably once it is chopped into 255-octet pieces.
How resolvers reassemble the pieces
This is the detail that trips everyone up. When a resolver returns a multi-string TXT record, the consuming application concatenates the strings with nothing between them. No space, no separator, no newline. The byte sequence of string two follows the last byte of string one directly. DKIM and SPF both expect this empty-string concatenation, so the split must fall at a point where joining the halves with no delimiter reproduces the exact original value.
| You publish | Resolver returns the value as |
|---|---|
| "abc" "def" | abcdef |
| "abc " "def" | abc def |
| "v=spf1 include:_spf" ".example.com -all" | v=spf1 include:_spf.example.com -all |
The middle row shows the classic failure. A stray trailing space inside the first quotes becomes a real space in the joined value, turning a valid key or policy into gibberish. The reverse mistake is just as common: splitting in the middle of a word and expecting the viewer to reinsert a space that was never there. Because the concatenation is literal and delimiter-free, the only safe rule is that the pieces, joined end to end with nothing between them, must equal the original value byte for byte.
The concatenation gotchas that break records
- Accidental spaces at a boundary. If your split lands mid-token and you add a space to "tidy up" the quotes, the concatenated result no longer matches the signing key or the SPF syntax. Split anywhere, but add nothing.
- Treating multiple strings as multiple records. Two TXT strings in one record concatenate into one value. Two separate TXT records at the same name are two independent values, which for SPF is an immediate permerror because only one SPF record is allowed per name.
- A dashboard that splits for you, then you split again. Many providers accept the full value and chunk it internally. If you pre-split and the provider splits again, you can end up with broken boundaries. Know which your provider does.
- Base64 keys broken on a meaningful character. DKIM keys are base64. The join must reproduce the exact base64 string, so verify after publishing rather than trusting the dashboard preview.
Checking what actually got published
Never trust the editor view alone. Query the live record and look at how it comes back. With dig, the default output shows each character-string in its own set of quotes, which reveals exactly where the splits landed.
$ dig TXT selector._domainkey.example.com +short
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA" "nMoJK1qQ0lFzpF9yAbcD...wIDAQAB"
If you want to see the reassembled single value as an application would use it, strip the quotes and spaces between segments, or use a tool that performs the concatenation for you. The key question is always the same: does joining the quoted chunks with no separator give back the exact value you intended?
SPF has a second, separate limit
The 255-character string limit is about physical encoding. SPF layers its own logical limit on top: an SPF evaluation may trigger at most 10 DNS lookups via mechanisms like include, a, and mx. A long SPF record that is split correctly into multiple strings can still fail if it exceeds that lookup budget. The two problems are unrelated, so rule out both. The string split is about the record fitting the wire format; the lookup limit is about how much work resolving the policy requires.
| Limit | Applies to | Failure if exceeded |
|---|---|---|
| 255 octets per string | Any TXT record | Value cannot be stored in one string |
| 10 DNS lookups | SPF evaluation | SPF permerror |
Verify the published record resolves cleanly
A split that looks fine in one resolver can read differently once caches update, so confirm the record is live and intact everywhere before you rely on it. Run the name through the Valla DNS propagation checker to see the TXT value as resolvers around the world return it, then validate the reassembled result with our SPF and DKIM guides. Getting the split right once, and checking it, saves you from chasing mail-delivery failures that trace back to a single misplaced space.