openpyxl InvalidFileException: does not support file format (tested)
openpyxl.utils.exceptions.InvalidFileException: openpyxl does not support .csv file format (or the old .xls file format) comes from the file extension: openpyxl only opens .xlsx, .xlsm, .xltx and .xltm. Read CSVs with read_csv and .xls files with xlrd.
1. Four files, four different errors
from openpyxl import load_workbook
open("/tmp/data.csv", "w").write("a,b\n1,2\n")
open("/tmp/old.xls", "wb").write(bytes.fromhex("d0cf11e0a1b11ae1") + b"\0" * 504) # OLE2 header, like a real .xls
open("/tmp/report.xlsx", "w").write("<html><body>Session expired</body></html>")
for p in ["/tmp/data.csv", "/tmp/old.xls", "/tmp/report.xlsx", "/tmp/nope.xlsx"]:
try:
load_workbook(p)
except Exception as e:
print(f"{p}: {type(e).__module__}.{type(e).__name__}: {e}")
Output:
/tmp/data.csv: openpyxl.utils.exceptions.InvalidFileException: openpyxl does not support .csv file format, please check you can open it with Excel first. Supported formats are: .xlsx,.xlsm,.xltx,.xltm
/tmp/old.xls: openpyxl.utils.exceptions.InvalidFileException: openpyxl does not support the old .xls file format, please use xlrd to read this file, or convert it to the more recent .xlsx file format.
/tmp/report.xlsx: zipfile.BadZipFile: File is not a zip file
/tmp/nope.xlsx: builtins.FileNotFoundError: [Errno 2] No such file or directory: '/tmp/nope.xlsx'
load_workbook() first checks the extension. .csv and any other non-Excel extension raise InvalidFileException with the list of supported formats (.xlsx, .xlsm, .xltx, .xltm). A .xls gets its own message: openpyxl never reads the old binary Excel format. A file named .xlsx that is not really one (here an HTML page saved by a download) gets past the extension check and fails as zipfile.BadZipFile, because a real .xlsx is a zip archive.
2. Read each format with the right tool
import pandas as pd
open("/tmp/data.csv", "w").write("a,b\n1,2\n")
try:
pd.read_excel("/tmp/data.csv")
except Exception as e:
print(f"read_excel(.csv): {type(e).__name__}: {e}")
print(pd.read_csv("/tmp/data.csv").to_dict("records"))
with open("/tmp/old.xls", "rb") as f: head = f.read(8)
print("old.xls first bytes:", head.hex(), "-> OLE2 (real .xls)" if head == bytes.fromhex("d0cf11e0a1b11ae1") else "")
with open("/tmp/report.xlsx", "rb") as f: print("report.xlsx first bytes:", f.read(15))
Output:
read_excel(.csv): ValueError: Excel file format cannot be determined, you must specify an engine manually.
[{'a': 1, 'b': 2}]
old.xls first bytes: d0cf11e0a1b11ae1 -> OLE2 (real .xls)
report.xlsx first bytes: b'<html><body>Ses'
For a CSV, use pd.read_csv() or the csv module; pd.read_excel() on a .csv fails with ValueError: Excel file format cannot be determined. For a real .xls (first bytes d0cf11e0a1b11ae1), use pd.read_excel(path, engine="xlrd") with pip install xlrd, or convert it to .xlsx once in Excel or LibreOffice. If the first bytes are <html, you downloaded an error or login page, not a spreadsheet: fix the download.
Checklist
- Extension is
.xlsx/.xlsm/.xltx/.xltm: otherwiseInvalidFileException. - The file really is that format: a real .xlsx starts with
PK(zip). A renamed CSV or HTML file fails later asBadZipFile. - Old
.xls: xlrd or convert; do not just rename it to .xlsx (that givesBadZipFile).
Related: BadZipFile: File is not a zip file · openpyxl IllegalCharacterError · Missing optional dependency openpyxl.
Frequently asked questions
Why does openpyxl say it does not support the old .xls file format?
openpyxl only reads the zip-based formats (.xlsx, .xlsm, .xltx, .xltm). Use xlrd (pd.read_excel(path, engine='xlrd')) or convert the file to .xlsx.
Can openpyxl open a CSV file?
No. load_workbook raises InvalidFileException for .csv. Use pandas.read_csv or the csv module.
Why do I get BadZipFile instead of InvalidFileException?
The file has an .xlsx extension but is not a zip archive: usually an HTML page from a failed download or a renamed CSV/XLS.
Written with AI assistance. Measured on 2026-10-23 with openpyxl 3.1.5, pandas 3.1.0 and Python 3.15.1 (python:3-slim in Docker). Each block was run verbatim and the output pasted unedited. PlainTables is our extension; Python and openpyxl are free.