{"record":{"id":"5344556842c80048","repo":"pola-rs/polars","slug":"a-more-recent-version-of-fastexcel-is-required-f-534455","errorCode":null,"errorMessage":"a more recent version of `fastexcel` is required for 'table_name' (>= 0.12.0; found {original_version})","messagePattern":"a more recent version of `fastexcel` is required for 'table_name' \\(>= 0\\.12\\.0; found (.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/spreadsheet/functions.py","lineNumber":1054,"sourceCode":"    table_name: str | None = None,\n    drop_empty_rows: bool,\n    drop_empty_cols: bool,\n    raise_if_empty: bool,\n) -> pl.DataFrame:\n    # if we have 'schema_overrides' and a more recent version of `fastexcel`\n    # we can pass translated dtypes to the engine to refine the initial parse\n    fastexcel = import_optional(\"fastexcel\")\n    fastexcel_version = parse_version(original_version := fastexcel.__version__)\n\n    if fastexcel_version < (0, 9) and \"schema_sample_rows\" in read_options:\n        msg = f\"a more recent version of `fastexcel` is required for 'schema_sample_rows' (>= 0.9; found {original_version})\"\n        raise ModuleUpgradeRequiredError(msg)\n    if fastexcel_version < (0, 10, 2) and \"use_columns\" in read_options:\n        msg = f\"a more recent version of `fastexcel` is required for 'use_columns' (>= 0.10.2; found {original_version})\"\n        raise ModuleUpgradeRequiredError(msg)\n    if table_name and fastexcel_version < (0, 12):\n        msg = f\"a more recent version of `fastexcel` is required for 'table_name' (>= 0.12.0; found {original_version})\"\n        raise ValueError(msg)\n\n    if columns:\n        if not isinstance(columns, list):\n            columns = list(columns)  # type: ignore[assignment]\n        read_options[\"use_columns\"] = columns\n\n    schema_overrides = schema_overrides or {}\n    if read_options.get(\"schema_sample_rows\") == 0:\n        # ref: https://github.com/ToucanToco/fastexcel/issues/236\n        del read_options[\"schema_sample_rows\"]\n        read_options[\"dtypes\"] = (\n            \"string\"\n            if fastexcel_version >= (0, 12, 1)\n            else dict.fromkeys(range(16384), \"string\")\n        )\n    elif schema_overrides and fastexcel_version >= (0, 10):\n        parser_dtypes = read_options.get(\"dtypes\", {})\n        for name, dtype in schema_overrides.items():","sourceCodeStart":1036,"sourceCodeEnd":1072,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/spreadsheet/functions.py#L1036-L1072","documentation":"Raised in _read_spreadsheet_calamine when the table_name parameter is used with fastexcel older than 0.12.0, because parser.load_table only exists from 0.12. Inconsistently with its sibling checks (432/433), this one is a plain ValueError, NOT a ModuleUpgradeRequiredError — so an `except ModuleUpgradeRequiredError` handler will not catch it. The engine import floor remains 0.7.0, so nothing warns earlier.","triggerScenarios":"pl.read_excel(src, table_name='SalesTable') with fastexcel 0.7.x–0.11.x installed; table_name arriving via a generic kwargs dict into read_excel on an environment with an older fastexcel.","commonSituations":"Adopting the (relatively new) table_name feature on a project whose lockfile still pins an old fastexcel; CI passing locally (newer env) but failing in prod images.","solutions":["Upgrade fastexcel to >= 0.12.0 (pip install -U 'fastexcel>=0.12')","If you cannot upgrade, read Excel tables via engine='openpyxl', which supports table_name natively","When catching this, remember it is ValueError — also catch ModuleUpgradeRequiredError separately for the sibling version checks"],"exampleFix":"# before (fastexcel 0.10.x)\npl.read_excel(src, table_name='SalesTable')\n\n# after (no fastexcel upgrade available)\npl.read_excel(src, table_name='SalesTable', engine='openpyxl')","handlingStrategy":"fallback","validationCode":"def fastexcel_at_least(major, minor, patch=0) -> bool:\n    import fastexcel\n    return tuple(int(p) for p in fastexcel.__version__.split('.')[:3]) >= (major, minor, patch)\n\nengine = 'calamine' if fastexcel_at_least(0, 12) else 'openpyxl'\ndf = pl.read_excel(src, table_name='Sales', engine=engine)","typeGuard":null,"tryCatchPattern":"# NOTE: this check raises plain ValueError, NOT ModuleUpgradeRequiredError\ntry:\n    df = pl.read_excel(src, table_name='Sales')\nexcept ValueError as e:\n    if \"'table_name'\" in str(e) and 'fastexcel' in str(e):\n        df = pl.read_excel(src, table_name='Sales', engine='openpyxl')\n    else:\n        raise","preventionTips":["Gate table_name usage on fastexcel >= 0.12 at startup and fall back to engine='openpyxl' otherwise","Remember the exception type inconsistency: table_name raises ValueError while sibling checks raise ModuleUpgradeRequiredError — catch both","Encode the version floor in your lockfile rather than handling it at runtime when possible"],"tags":["polars","excel","calamine","fastexcel","version","table","upgrade"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}