{"record":{"id":"840f2976e58f910e","repo":"pola-rs/polars","slug":"read-database-queries-require-at-least-module-n","errorCode":null,"errorMessage":"`read_database` queries require at least {module_name} version {minimum_version}","messagePattern":"`read_database` queries require at least (.+?) version (.+?)","errorType":"exception","errorClass":"ModuleUpgradeRequiredError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/database/_executor.py","lineNumber":151,"sourceCode":"        if self.can_close_cursor and hasattr(self.cursor, \"close\"):\n            from sqlalchemy.ext.asyncio.exc import AsyncContextNotStarted\n\n            with suppress(AsyncContextNotStarted):\n                await self.cursor.close()\n\n    @staticmethod\n    def _check_module_version(module_name: str, minimum_version: str) -> None:\n        \"\"\"Check the module version against a minimum required version.\"\"\"\n        mod = __import__(module_name)\n        with suppress(AttributeError):\n            module_version: tuple[int, ...] | None = None\n            for version_attr in (\"__version__\", \"version\"):\n                if isinstance(ver := getattr(mod, version_attr, None), str):\n                    module_version = parse_version(ver)\n                    break\n            if module_version and module_version < parse_version(minimum_version):\n                msg = f\"`read_database` queries require at least {module_name} version {minimum_version}\"\n                raise ModuleUpgradeRequiredError(msg)\n\n    def _fetch_arrow(\n        self,\n        driver_properties: ArrowDriverProperties,\n        *,\n        batch_size: int | None,\n        iter_batches: bool,\n    ) -> Iterable[pa.RecordBatch]:\n        \"\"\"Yield Arrow data as a generator of one or more RecordBatches or Tables.\"\"\"\n        fetch_batches = driver_properties[\"fetch_batches\"]\n        if not iter_batches or fetch_batches is None:\n            fetch_method = driver_properties[\"fetch_all\"]\n            res = getattr(self.result, fetch_method)()\n\n            if isinstance(res, Iterable):\n                yield from res\n            else:\n                yield res","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/database/_executor.py#L133-L169","documentation":"Before using an Arrow-based fetch path, ConnectionExecutor._check_module_version imports the driver module, reads its __version__/version, and compares against the minimum polars requires for that path (ARROW_DRIVER_REGISTRY entries, e.g. aiosqlite, adbc_driver_manager, turbodbc). If the installed version is older, it raises ModuleUpgradeRequiredError (a ModuleNotFoundError subclass), after first trying any lower-requirement fallback driver properties in the registry. The with suppress(AttributeError) means a module with no version attribute passes silently - only a parseable, too-old version raises.","triggerScenarios":"pl.read_database(...) with an ADBC/turbodbc/aiosqlite-backed connection whose package is below the registry minimum, e.g. adbc-driver-manager 0.5 when the path requires >=0.9; docker images or lambda layers pinning old driver wheels; pip resolving an old version due to a conflicting constraint.","commonSituations":"Locked dependency files (requirements.txt, poetry.lock) holding drivers back; CI image caching an old wheel; upgrading polars without upgrading the database driver stack.","solutions":["Upgrade the named module to at least the stated minimum: pip install -U 'adbc-driver-manager>=<minimum_version>' (use the module_name/minimum_version from the message)","If you cannot upgrade, choose a different connection style (e.g. plain DBAPI cursor instead of ADBC, or read_database_uri with connectorx)","Check for dependency constraints forcing the old version: pip check / pip install --upgrade --force-reinstall <module>"],"exampleFix":"# before: ModuleUpgradeRequiredError: `read_database` queries require at least adbc_driver_manager version 0.9.0\npl.read_database('SELECT * FROM t', connection=adbc_conn)\n\n# after\n# pip install -U 'adbc-driver-manager>=0.9.0'\npl.read_database('SELECT * FROM t', connection=adbc_conn)","handlingStrategy":"validation","validationCode":"from importlib import metadata\n\ndef ensure_version(module_name: str, minimum: str) -> None:\n    installed = metadata.version(module_name)\n    if tuple(map(int, installed.split('.')[:3])) < tuple(\n        map(int, minimum.split('.')[:3])\n    ):\n        raise RuntimeError(\n            f'{module_name} {installed} too old for polars; need >= {minimum}'\n        )\n\nensure_version('adbc_driver_manager', '0.9.0')\ndf = pl.read_database(query, connection=adbc_conn)","typeGuard":null,"tryCatchPattern":"from polars.exceptions import ModuleUpgradeRequiredError\n\ntry:\n    df = pl.read_database(query, connection=conn)\nexcept ModuleUpgradeRequiredError as err:\n    # message names module + minimum version; surface to deployment tooling\n    raise RuntimeError(f'dependency upgrade required: {err}') from err","preventionTips":["Pin driver floors (adbc-driver-manager, turbodbc, aiosqlite, connectorx) in requirements alongside the polars pin","Run a startup version check with importlib.metadata before opening connections","Re-verify driver versions whenever polars is upgraded - registry minimums move between releases"],"tags":["polars","database","version","dependency","adbc","moduleupgraderequirederror"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}