odoo/odoo · error · ImportValidationError
Import file has no content or is corrupt
Error message
Import file has no content or is corrupt
What it means
Raised in parse_preview when _read_file() succeeds but reports file_length <= 0, meaning the reader found zero data rows (or a negative count from an empty sheet). It guards the preview step against empty or structurally broken files before any field matching happens.
Source
Thrown at addons/base_import/models/base_import.py:1024
fields-matching between the import's file data and the model's
columns.
If the headers are not requested (not options.has_headers),
returned ``matches`` and ``headers`` are both ``False``.
:param int count: number of preview lines to generate
:param options: format-specific options.
CSV: {quoting, separator, headers}
:type options: {str, str, str, bool}
:returns: ``{fields, matches, headers, preview} | {error, preview}``
:rtype: {dict(str: dict(...)), dict(int, list(str)), list(str), list(list(str))} | {str, str}
"""
self.ensure_one()
fields_tree = self.get_fields_tree(self.res_model)
try:
file_length, data_rows = self._read_file(options)
if file_length <= 0:
raise ImportValidationError(_("Import file has no content or is corrupt"))
preview = data_rows[:count]
# Get file headers
if options.get('has_headers') and preview:
# We need the header types before matching columns to fields
headers = preview.pop(0)
header_types = self._extract_headers_types(headers, preview, options)
else:
header_types, headers = {}, []
# Get matches: the ones already selected by the user or propose a new matching.
matches = {}
# If user checked to the advanced mode, we re-parse the file but we keep the mapping "as is".
# No need to make another mapping proposal
if options.get('keep_matches') and options.get('fields'):
for index, match in enumerate(options.get('fields', [])):
if match:View on GitHub (pinned to 1e661df964)
Solutions
- Open the file and confirm it actually contains data rows on the first sheet; re-export if empty.
- For multi-sheet workbooks pass options['sheet'] with the correct sheet name (or pick it in the wizard).
- Verify the file is not truncated/corrupt (re-download or re-create it) - a valid XLSX opens in Excel.
- In custom flows, check row count client-side before upload (e.g. read the CSV and count non-blank lines).
Example fix
# before
record.parse_preview(20, {}) # empty first sheet -> 'Import file has no content or is corrupt'
# after: point at the sheet that has data
record.parse_preview(20, {'sheet': 'Sheet2'})
# or check emptiness first
import csv, io
rows = [r for r in csv.reader(io.StringIO(text)) if any(c.strip() for c in r)]
assert rows, 'refusing to upload an empty file' Defensive patterns
Strategy: validation
Validate before calling
import csv, io
def csv_has_rows(data: bytes, options: dict) -> bool:
text = data.decode(options.get('encoding') or 'utf-8-sig')
return any(any(c.strip() for c in row) for row in csv.reader(io.StringIO(text)))
def xlsx_has_rows(data: bytes, sheet: str | None = None) -> bool:
import openpyxl
book = openpyxl.load_workbook(io.BytesIO(data), data_only=True)
target = book[sheet] if sheet else book.worksheets[0]
return target.max_row > 0 Try / catch
try:
record.parse_preview(count, options)
except ImportValidationError as e:
if 'no content or is corrupt' in str(e):
return {'error': 'empty-file', 'hint': 'check sheet selection and re-export'}
raise Prevention
- Check row counts client-side before uploading.
- For multi-sheet files always pass options['sheet'] explicitly.
- Recreate files that fail to open cleanly in a spreadsheet editor (truncated transfers).
When it happens
Trigger: Uploading an empty CSV/XLSX/ODS, a file whose first sheet has no rows (data on another sheet without options['sheet'] set), a CSV containing only blank lines, or a file so corrupt readers return max_row == 0.
Common situations: User exports a filtered view that happens to contain no rows; file was truncated during transfer; XLSX with data only on 'Sheet2' while the importer defaults to the first sheet; whitespace-only CSV.
Related errors
- Error while importing records: Text Delimiter should be a si
- Invalid cell format at row %(row)s, column %(col)s: %(cell_v
- There was an issue decoding the file using encoding “%s”. Th
- There was an issue decoding the file using encoding “%s”. Th
- You must configure at least one field to import
AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15).
Data as JSON: /api/errors/f4232845deb08fa2.
Report an issue: GitHub.