{"record":{"id":"ce5fcba6ec86e104","repo":"pola-rs/polars","slug":"no-matching-sheet-found-when-sheet-name-is-name","errorCode":null,"errorMessage":"no matching sheet found when `sheet_name` is {name!r}","messagePattern":"no matching sheet found when `sheet_name` is (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/spreadsheet/functions.py","lineNumber":812,"sourceCode":"        sheet_names.append(name)\n        return_multiple_sheets = False\n    elif sheet_id == 0:\n        sheet_names.extend(ws[\"name\"] for ws in worksheets)\n        return_multiple_sheets = True\n    else:\n        return_multiple_sheets = (\n            (isinstance(sheet_name, Sequence) and not isinstance(sheet_name, str))\n            or isinstance(sheet_id, Sequence)\n            or sheet_id == 0\n        )\n        if names := (\n            (sheet_name,) if isinstance(sheet_name, str) else sheet_name or ()\n        ):\n            known_sheet_names = {ws[\"name\"] for ws in worksheets}\n            for name in names:\n                if name not in known_sheet_names:\n                    msg = f\"no matching sheet found when `sheet_name` is {name!r}\"\n                    raise ValueError(msg)\n                sheet_names.append(name)\n        else:\n            ids = (sheet_id,) if isinstance(sheet_id, int) else sheet_id or ()\n            sheet_names_by_idx = {\n                idx: ws[\"name\"]\n                for idx, ws in enumerate(worksheets, start=1)\n                if (sheet_id == 0 or ws[\"index\"] in ids or ws[\"name\"] in names)\n            }\n            for idx in ids:\n                if (name := sheet_names_by_idx.get(idx)) is None:\n                    msg = f\"no matching sheet found when `sheet_id` is {idx}\"\n                    raise ValueError(msg)\n                sheet_names.append(name)\n\n    return sheet_names, return_multiple_sheets  # type: ignore[return-value]\n\n\ndef _initialise_spreadsheet_parser(","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/spreadsheet/functions.py#L794-L830","documentation":"Raised by pl.read_excel / pl.read_ods in _get_sheet_names (a ValueError) when a requested sheet_name is not in the set of worksheet names reported by the parsing engine. Names are matched exactly (case-sensitive, whitespace-sensitive), and the list reflects what the engine sees — e.g. xlsx2csv excludes hidden sheets if you set engine_options={'exclude_hidden_sheets': True}. Validation happens per name, so the first unknown name aborts the whole read.","triggerScenarios":"pl.read_excel('f.xlsx', sheet_name='sheet1') when the workbook has 'Sheet1'; sheet_name=['Data','Summary'] where 'Summary' does not exist; naming a hidden sheet after enabling exclude_hidden_sheets; names with trailing spaces copied from Excel.","commonSituations":"Workbooks regenerated by an upstream process with renamed/reordered tabs; locale-dependent sheet names; hardcoded names in ETL jobs; Excel sheet names that differ from the visible tab label after trailing-space trimming.","solutions":["List the real sheet names first (openpyxl.load_workbook(path, read_only=True).sheetnames) and pass one of those","Fix the typo / exact casing / trailing whitespace in sheet_name","If sheets vary across inputs, read all sheets with sheet_id=0 and work from the returned dict keys","If the sheet is hidden, drop exclude_hidden_sheets from engine_options or unhide it in the source file"],"exampleFix":"# before\npl.read_excel('f.xlsx', sheet_name='Data ')  # trailing space -> ValueError\n\n# after\nimport openpyxl\nnames = openpyxl.load_workbook('f.xlsx', read_only=True).sheetnames\npl.read_excel('f.xlsx', sheet_name=names[0])","handlingStrategy":"validation","validationCode":"import openpyxl\n\ndef sheet_names(path):\n    with openpyxl.load_workbook(path, read_only=True) as wb:\n        return list(wb.sheetnames)\n\nnames = sheet_names('report.xlsx')\ntarget = 'Data'\nif target not in names:  # exact, case-sensitive match as polars does\n    target = next((n for n in names if n.strip() == target.strip()), None)\nassert target, f'sheet {target!r} not in {names}'\ndf = pl.read_excel('report.xlsx', sheet_name=target)","typeGuard":"def known_sheet_name(name: str, path: str) -> bool:\n    with openpyxl.load_workbook(path, read_only=True) as wb:\n        return name in wb.sheetnames","tryCatchPattern":"try:\n    df = pl.read_excel(src, sheet_name=name)\nexcept ValueError as e:\n    if 'no matching sheet' in str(e):\n        frames = pl.read_excel(src, sheet_id=0, infer_schema_length=1)  # discover real names\n        raise ValueError(f'available sheets: {list(frames)}') from e\n    raise","preventionTips":["Never hardcode sheet names without a fallback; verify against openpyxl sheetnames or read sheet_id=0 once and use the dict keys","Match names exactly — polars is case- and whitespace-sensitive","If sheets come from user files, treat 'sheet not found' as expected input error with a clear message listing available sheets"],"tags":["polars","excel","ods","sheet-selection","lookup","case-sensitivity"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}