{"record":{"id":"4582c39f841d6670","repo":"pola-rs/polars","slug":"a-more-recent-version-of-fastexcel-is-required-f-4582c3","errorCode":null,"errorMessage":"a more recent version of `fastexcel` is required for 'use_columns' (>= 0.10.2; found {original_version})","messagePattern":"a more recent version of `fastexcel` is required for 'use_columns' \\(>= 0\\.10\\.2; found (.+?)\\)","errorType":"exception","errorClass":"ModuleUpgradeRequiredError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/spreadsheet/functions.py","lineNumber":1051,"sourceCode":"    read_options: dict[str, Any],\n    schema_overrides: SchemaDict | None,\n    columns: Sequence[int] | Sequence[str] | None,\n    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        )","sourceCodeStart":1033,"sourceCodeEnd":1069,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/spreadsheet/functions.py#L1033-L1069","documentation":"Raised as ModuleUpgradeRequiredError in _read_spreadsheet_calamine when read_options contains 'use_columns' and the installed fastexcel is older than 0.10.2. The key is set automatically whenever you pass the top-level `columns` parameter to read_excel with the calamine engine, and can also be supplied directly. Note the gap: fastexcel 0.10.0/0.10.1 pass the bytes check (error 427) but still fail here.","triggerScenarios":"pl.read_excel(src, columns=['a','c']) with fastexcel < 0.10.2 (columns is rewritten into read_options['use_columns']); or read_options={'use_columns': [0, 2]} passed explicitly with an older fastexcel.","commonSituations":"Environments pinned to fastexcel 0.9–0.10.1 (e.g. to satisfy the schema_sample_rows floor); code that read full sheets fine until someone added column selection.","solutions":["Upgrade fastexcel to >= 0.10.2","No upgrade possible: read all columns and select afterwards — df = pl.read_excel(src)[['a','c']] or df.select(columns)","Or use engine='openpyxl'/'xlsx2csv', which handle columns independent of the fastexcel version"],"exampleFix":"# before (fastexcel < 0.10.2)\ndf = pl.read_excel(src, columns=['a', 'c'])\n\n# after (no upgrade)\ndf = pl.read_excel(src).select('a', 'c')","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\ncolumns = ['a', 'c'] if fastexcel_at_least(0, 10, 2) else None\ndf = pl.read_excel(src, columns=columns)\nif columns is None:\n    df = df.select('a', 'c')  # post-select on old fastexcel","typeGuard":null,"tryCatchPattern":"from polars.exceptions import ModuleUpgradeRequiredError\ntry:\n    df = pl.read_excel(src, columns=cols)\nexcept ModuleUpgradeRequiredError as e:\n    if \"'use_columns'\" in str(e):\n        df = pl.read_excel(src).select(cols)  # fallback: select after full read\n    else:\n        raise","preventionTips":["Note the version gap: fastexcel 0.10.0/0.10.1 pass the bytes check but still fail column selection","Keep a helper that probes fastexcel.__version__ once and chooses pushdown vs post-select","Lockfile CI: fail the build if fastexcel < 0.10.2 and any read passes `columns`"],"tags":["polars","excel","calamine","fastexcel","version","columns","upgrade"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}