Why Excel Says the File Format or Extension Is Not Valid
Excel says the file format or extension is not valid when the content does not match the extension. Identify the real format from its first bytes and fix it.

The message reads: "Excel cannot open the file 'report.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file." People take it to mean the file is damaged. It rarely is. It means the extension says one thing and the contents say another. This post shows how to read the real format from the first bytes, the usual ways a mismatch arises, and the fix for each. It is a spoke of understanding Excel errors when data comes from code.
What the extension promises
Each Excel extension promises a particular container.
| Extension | What it should be |
|---|---|
.xlsx, .xlsm | A zip archive of XML parts (Office Open XML) |
.xls | A binary compound file (BIFF), the pre-2007 format |
.xlsb | A zip archive containing binary parts |
.csv | Plain text with delimiters |
Excel checks the content against the extension when it opens the file. If a .xlsx is not a zip, or an .xls is not a compound file, it refuses with the format message. For .xls it sometimes opens the file anyway after a warning, "The file format and extension of 'x.xls' don't match", because it recognizes a CSV or HTML table inside and offers to open it, which is a courtesy for a very common mistake.
Read the first bytes
You can tell what a file is without opening it. Look at its first few bytes. In a terminal:
head -c 8 report.xlsx | xxd
file report.xlsxIn Python:
with open("report.xlsx", "rb") as f:
head = f.read(8)
print(head)Compare the result with this table:
| Starts with | Meaning |
|---|---|
50 4B 03 04 (PK followed by two bytes) | A zip archive, so xlsx, xlsm, docx and similar |
D0 CF 11 E0 A1 B1 1A E1 | A compound file, so a real .xls, or an encrypted .xlsx |
3C 68 74 6D 6C (<html) or 3C 21 44 4F (<!DO) | HTML saved with an Excel extension |
3C 3F 78 6D 6C (<?xml) | XML, possibly an XML Spreadsheet 2003 file |
EF BB BF then text | A UTF-8 CSV with a byte order mark |
| plain letters, commas, digits | A CSV or TSV |
7B or 5B ({ or ``) | JSON |
25 50 44 46 (%PDF) | A PDF |
If the file size is zero, or a few hundred bytes of an HTML error page, the cause is a failed download or a script that wrote an error message into the output file. Open it in a text editor first: when the content is an HTML page from a login redirect, you have found the bug, and it has nothing to do with Excel.
The common causes
A script wrote HTML or CSV with an Excel name. A web application "exports to Excel" by echoing an HTML table with the header Content-Type: application/vnd.ms-excel and a .xls file name. Excel recognizes it and offers to open it, with a warning, but a .xlsx name on the same content gives the format error. A CSV renamed to .xlsx does the same.
An encrypted workbook. A password-protected xlsx is stored as a compound file, not a zip, so it starts with D0 CF 11 E0. Tools that expect a zip report a format problem, and Excel itself asks for the password ([password protected Excel files and scripts).
A truncated or empty download. The server returned fewer bytes than promised, or the proxy replaced the body. Compare the size with what the source reports, and re-download.
A file saved in the wrong format. Someone chose Save As, .xlsx, but the format drop-down said CSV. It happens with some tools that apply the extension without converting.
A renamed file. Changing .xls to .xlsx in Explorer does not convert anything. The content is still the old binary format and Excel rejects it.
A security setting. Excel's file block settings can refuse older formats; the message then differs and refers to the Trust Center.
Fix it
Decide by what the first bytes say.
Zip, but the name is wrong: rename to
.xlsx. Check the contents withunzip -l report.xlsx: a real workbook lists[Content_Types].xml,xl/workbook.xmlandxl/worksheets/.Compound file with an .xlsx name: rename to
.xls, or open it and save as xlsx. If it asks for a password, it is encrypted.HTML: rename to
.htmland open it in a browser. If it is an error page, fix the request. If it is a table, read it withpandas.read_html, or open it in Excel via Data, From Web, or save the page as csv.CSV or TSV: rename to
.csvand open it through Data, From Text/CSV so you choose the delimiter and the encoding (Excel and CSV files shared with other tools).XML: if it is the XML Spreadsheet 2003 format, rename to
.xmland open it in Excel; otherwise it is data to parse.
Then repair the producer. If your code writes the file, use a real writer: openpyxl or XlsxWriter for xlsx, or to_excel in pandas. Writing HTML and naming it .xls is a shortcut with known costs, including this message, security warnings and lost types. Set the response header correctly if serving the file from a web app: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet for xlsx.
Add a check to the pipeline
When files arrive from outside, check before reading. A small function can name the real type:
def sniff(path):
with open(path, "rb") as f:
head = f.read(8)
if head.startswith(b"PK\x03\x04"):
return "zip (xlsx or similar)"
if head.startswith(b"\xd0\xcf\x11\xe0"):
return "compound file (xls or encrypted)"
if head.lstrip().lower().startswith((b"<html", b"<!doc")):
return "html"
return "other"Call it before read_excel and fail with a message that says what the file is. A pipeline that reports "expected xlsx, got html" saves the hour spent staring at a traceback from deep inside a library. The same check belongs on any upload endpoint, which should also verify size and content before processing (checking an Excel upload before reading it).
Python errors that mean the same thing
The same mismatch appears in code as different messages:
zipfile.BadZipFile: File is not a zip filefrom openpyxl on a non-zip (fixing BadZipFile when reading an XLSX).xlrd.biffh.XLRDError: Excel xlsx file; not supportedfrom xlrd given an xlsx (the Python xlrd error).openpyxl.utils.exceptions.InvalidFileExceptionfor an unsupported extension such as.xls.
Each of these says "I was handed something other than what the name promised". Reading the first bytes answers all of them.
When the format message hides a different problem
The file really is corrupt. A zip whose end record is missing starts with PK but fails to open. unzip -t file.xlsx tests it (Excel cannot open the file because it is corrupt).
The workbook opens but complains. A message about unreadable content is a different problem, usually invalid XML inside a valid package.
Protected View blocks it. A file from the internet opens read-only with a yellow bar. That is a security feature, not a format problem.
The path is wrong. A shortcut or a network file that has moved can produce misleading messages. Try copying the file locally and opening it from there.
See Microsoft's page on file formats supported in Excel and the open standard in ECMA-376 Office Open XML. To convert a small CSV, use the CSV to JSON converter.


