pola-rs/polars · error · FileNotFoundError
{source}
Error message
{source} What it means
Raised by pl.read_excel / pl.read_ods in _initialise_spreadsheet_parser as a plain builtin FileNotFoundError (message is just the path) when source is a str that does not exist on disk. The check runs before any engine is loaded, so no optional dependency error can mask it. Note the string is first normalized (e.g. ~ expansion) and URLs are fetched earlier, so this only concerns local filesystem paths.
Source
Thrown at py-polars/src/polars/io/spreadsheet/functions.py:837
if (sheet_id == 0 or ws["index"] in ids or ws["name"] in names)
}
for idx in ids:
if (name := sheet_names_by_idx.get(idx)) is None:
msg = f"no matching sheet found when `sheet_id` is {idx}"
raise ValueError(msg)
sheet_names.append(name)
return sheet_names, return_multiple_sheets # type: ignore[return-value]
def _initialise_spreadsheet_parser(
engine: str | None,
source: str | IO[bytes] | bytes,
engine_options: dict[str, Any],
) -> tuple[Callable[..., pl.DataFrame], Any, list[dict[str, Any]]]:
"""Instantiate the indicated spreadsheet parser and establish related properties."""
if isinstance(source, str) and not Path(source).exists():
raise FileNotFoundError(source)
if engine == "xlsx2csv": # default
xlsx2csv = import_optional("xlsx2csv")
# establish sensible defaults for unset options
for option, value in {
"exclude_hidden_sheets": False,
"skip_empty_lines": False,
"skip_hidden_rows": False,
"floatformat": "%f",
}.items():
engine_options.setdefault(option, value)
if isinstance(source, bytes):
source = BytesIO(source)
parser = xlsx2csv.Xlsx2csv(source, **engine_options)
sheets = parser.workbook.sheetsView on GitHub (pinned to df599052da)
Solutions
- Resolve and verify the path first: Path(source).expanduser().resolve() and check .exists()
- Check your working directory (os.getcwd()) if the path is relative
- If the file should have been produced by an earlier step, verify that step succeeded before reading
Example fix
# before
pl.read_excel('data/report.xlsx')
# after
from pathlib import Path
path = Path('data/report.xlsx').expanduser().resolve()
if not path.exists():
raise FileNotFoundError(f'missing input file: {path}')
pl.read_excel(path) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
path = Path(source).expanduser().resolve() if isinstance(source, str) else Path(source)
if not path.is_file():
raise FileNotFoundError(f'input workbook not found: {path} (cwd={Path.cwd()})')
df = pl.read_excel(path) Try / catch
try:
df = pl.read_excel(src)
except FileNotFoundError:
# plain builtin exception; polars' message is just the path
log.error('workbook missing: %s', src)
raise Prevention
- Resolve paths to absolute (expanduser().resolve()) before handing them to read_excel
- In scheduled jobs/notebooks, assert the cwd or use absolute paths from config
- Validate that the producing pipeline step wrote the file (size > 0) before reading
When it happens
Trigger: pl.read_excel('data/report.xlsx') when the relative path is wrong for the current working directory; a typo in the filename; a file that a previous pipeline step failed to write; paths read from config/env vars that are unset or stale.
Common situations: Scripts run from a different cwd than expected (cron, notebooks, Airflow workers), Windows/Unix path separator mixups, race conditions where the file is created after the read starts.
Related errors
- no workbook found at path {src!r}
- cannot specify both `columns` and `read_options["columns"]`
- the values of `has_header` and `read_options["has_header"]`
- cannot specify both `infer_schema_length` and `read_options[
- cannot specify both `sheet_name` ({sheet_name!r}) and `sheet
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/d6725c73df878e66.
Report an issue: GitHub.