Twilio errors · 2026
Twilio error 21217: “phone number does not appear to be valid”, and the list fix behind it
Last updated September 4, 2026
Twilio's page for 21217 is one sentence long: check the phone number and try again. That is the right advice for a developer testing one number and useless for someone who just imported 3,000 rows from a lead vendor and watched a fifth of them fail. The numbers are usually fine. The formatting is not, and the spreadsheet they passed through made it worse. Here is what Twilio wants, the eight ways a list breaks it, the one formula that fixes most of them, and how to tell the leftovers from genuinely dead numbers.
The short answer
Twilio only dials E.164: a plus, the country code, the number, nothing else (+14155552671). Normalise the column before import, keep it formatted as text so the spreadsheet does not turn it into 4.15556E+09, put extensions in their own column, and set the country for non-US lists. Rows that still fail are a digit short or genuinely dead, and a line-type lookup at about a cent each sorts those.
Eight ways a list produces 21217
| As it arrives | What Twilio needs | What happened |
|---|---|---|
| (415) 555-2671 | +14155552671 | Brackets, space and dash stripped; +1 added |
| 415.555.2671 | +14155552671 | Dots stripped; +1 added |
| 1-415-555-2671 | +14155552671 | Leading 1 kept, plus added |
| 4155552671.0 | +14155552671 | Spreadsheet decimal removed |
| 4.15556E+09 | cannot recover | Digits were lost when the sheet rounded; re-export the column as text |
| 415-555-2671 x204 | +14155552671 | Extension moved to its own column |
| 07700 900123 (UK) | +447700900123 | Trunk 0 dropped, +44 added; needs the list's country set to GB |
| 555-2671 | cannot recover | No area code; seven digits is not a dialable number |
The one-formula fix in Google Sheets
For a US or Canadian list with raw numbers in column A, put this in B2 and fill down. It strips everything that is not a digit, prepends +1 to ten-digit numbers, adds a plus to eleven-digit numbers that already start with 1, and leaves anything else blank so you can see it:
=IF(LEN(REGEXREPLACE(TO_TEXT(A2),"[^0-9]",""))=10,
"+1"®EXREPLACE(TO_TEXT(A2),"[^0-9]",""),
IF(LEN(REGEXREPLACE(TO_TEXT(A2),"[^0-9]",""))=11,
"+"®EXREPLACE(TO_TEXT(A2),"[^0-9]",""),
""))Before you paste, select column B and set Format → Number → Plain text, or Sheets will helpfully turn +14155552671 back into a number and drop the plus on export. Then filter B for blanks: those rows are the ones with seven digits, letters, or two numbers in one cell, and they need a person. Extensions go in their own column; Twilio will not dial “x204” and a dialer can send the digits after connect instead. For UK, Irish or Australian lists the rule changes (drop the trunk zero, add the country code); the country-by-country versions are in how to clean a lead list before you dial it.
Why the spreadsheet is the usual culprit
A CSV that passes through Excel or Sheets has its phone column read as a number. The plus disappears because it is not a digit. Past about eleven digits the cell displays scientific notation, and on export it is written out that way, or as “4155552671.0” with a trailing decimal. Twilio parses neither. The safe habit is to open the CSV with the phone column forced to text, or to never round-trip a list through a spreadsheet at all: import the vendor's file straight into the dialer.
A good importer expects this. DialSheet's normalises every number to E.164 with a default country of US or Canada, undoes the trailing-decimal and scientific-notation forms, strips punctuation, adds the country code, and reports the rows it could not parse instead of dropping them. It exists because a 60,000-row import in September 2026 arrived with 21,528 numbers in the “.0” form, every one a valid US number underneath.
Formatting failure or dead number?
- Normalise first. Anything that cannot be normalised never reached Twilio; fix or drop it.
- Dedupe on the normalised value. Vendors sell the same number in three formats; you do not want to dial it three times.
- Look up what is left. Twilio Lookup's line-type intelligence costs about a cent a query and returns whether the number is assigned and whether it is mobile, landline or VoIP. Drop the unassigned ones; they are the real dead numbers and the source of the 21217s and 13224s that survive cleaning.
- Scrub before you dial. A clean list is not a compliant list; see do you have to scrub the DNC list.
Neighbouring errors
- 13224 is the Dial-verb twin and also covers well-formed numbers Twilio cannot route (premium ranges, non-existent area codes). See Twilio call blocked errors.
- 13227 / 21215 means the number is fine and the country is switched off. See geo permissions.
- 21210 is your caller ID, not the number you dialed. See error 21210.
Import the vendor's file as it is. The importer does the E.164.
DialSheet normalises, dedupes and reports the rows it could not parse, then dials on your own Twilio at ~$0.014/min. Free for one person up to 500 leads, $29 per 3 seats after. No Twilio? A managed line is $49/month.
Import a listQuestions people actually ask
What does Twilio error 21217 mean?
Twilio was asked to call a number it cannot parse as a valid phone number. Twilio expects E.164: a plus sign, the country code, then the national number with no spaces, brackets or dashes, for example +14155552671 or +447700900123. Anything else, a bare 4155552671 with no country code, a UK number with its trunk zero (+4407700...), a number with an extension in the same field, or a value Excel rewrote as 4.15556E+09, fails with 21217 before Twilio tries to route it. It is a formatting error in your data, not a Twilio outage and not a blocked number.
How do I format phone numbers for Twilio in Google Sheets?
Strip everything but digits, then add the country code. For a US list in column A: =IF(LEN(REGEXREPLACE(TO_TEXT(A2),"[^0-9]",""))=10,"+1"®EXREPLACE(TO_TEXT(A2),"[^0-9]",""),IF(LEN(REGEXREPLACE(TO_TEXT(A2),"[^0-9]",""))=11,"+"®EXREPLACE(TO_TEXT(A2),"[^0-9]",""),"")). Ten digits get +1 prepended, eleven digits starting with 1 get a plus, anything else becomes blank so you can see the rows that need a human. Format the output column as plain text before you export, or Sheets will drop the plus again.
Why does my CSV show phone numbers like 4.15556E+09?
Because a spreadsheet read the column as a number. Past about eleven digits Excel and Sheets display scientific notation, and on export they write it out that way, or write "4155552671.0" with a trailing decimal. Twilio cannot parse either. The fix is to keep the phone column as text (format the column as Plain text before pasting, or prefix values with an apostrophe) and to use an importer that undoes the damage. DialSheet's importer does: a 60,000-row import in September 2026 arrived with 21,528 numbers in the ".0" form and every one was recovered.
Is 21217 the same as 13224?
Close. 21217 is raised when the call is created through the REST API and the number fails validation; 13224 is the TwiML Dial equivalent and also covers numbers that are well-formed but unroutable, such as premium-rate ranges or an area code that does not exist. A browser dialer bridging your headset to the prospect usually reports 13224; a script creating calls directly reports 21217. Both start with the same fix: normalise the list to E.164.
How do I tell a formatting error from a dead number?
Normalise the whole list first. Rows that cannot be normalised (wrong digit count, letters, blanks) are formatting failures and never reached Twilio. Rows that normalise cleanly and still fail are candidates for dead: run them through a line-type lookup (Twilio Lookup is about a cent a query) to confirm the number is assigned and see whether it is mobile, landline or VoIP, then drop the unassigned ones. What is left is a list Twilio will dial.
What does DialSheet do with badly formatted numbers on import?
It normalises each number to E.164 with a default country of US or Canada, undoing trailing ".0" decimals and scientific notation from spreadsheets, stripping punctuation and adding the country code. Numbers that still cannot be parsed are reported rather than silently dropped, so you can fix the rows and re-import. Duplicates are matched on the normalised value, which is the only reliable way to dedupe a bought list.