{"record":{"id":"9e76dddd7d7c6439","repo":"pola-rs/polars","slug":"event-loop-stopped-before-future-completed","errorCode":null,"errorMessage":"Event loop stopped before Future completed.","messagePattern":"Event loop stopped before Future completed\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/_utils/nest_asyncio.py","lineNumber":283,"sourceCode":"    def run_forever(self):\n        with manage_run(self), manage_asyncgens(self):\n            while True:\n                self._run_once()\n                if self._stopping:\n                    break\n        self._stopping = False\n\n    def run_until_complete(self, future):\n        with manage_run(self):\n            f = asyncio.ensure_future(future, loop=self)\n            if f is not future:\n                f._log_destroy_pending = False\n            while not f.done():\n                self._run_once()\n                if self._stopping:\n                    break\n            if not f.done():\n                raise RuntimeError(\"Event loop stopped before Future completed.\")\n            return f.result()\n\n    def _run_once(self):\n        \"\"\"\n        Simplified re-implementation of asyncio's _run_once that\n        runs handles as they become ready.\n        \"\"\"\n        scheduled = self._scheduled\n        while scheduled and scheduled[0]._cancelled:\n            heappop(scheduled)\n\n        timeout = (\n            0\n            if self._ready or self._stopping\n            else min(max(scheduled[0]._when - self.time(), 0), 86400)\n            if scheduled\n            else None\n        )","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/_utils/nest_asyncio.py#L265-L301","documentation":"polars vendors nest_asyncio2 (polars/_utils/nest_asyncio.py) so pl.read_database can drive async drivers from synchronous code inside an already-running loop (polars/io/database/_utils.py). The patched run_until_complete loops _run_once until the future completes or _stopping is set; if the loop is stopped (loop.stop(), KeyboardInterrupt in the nested run, framework interactions) while the query future is incomplete, this RuntimeError is raised.","triggerScenarios":"pl.read_database(...) with an asyncio-based connector inside Jupyter when the loop is stopped or the cell is interrupted mid-query; another library calling loop.stop() during the nested run; mixing asyncio.run() with the patched loop.","commonSituations":"Notebooks with async database connectors; Ctrl-C during read_database; tornado/IPython loop management colliding with the nested run; server frameworks stopping the shared loop during shutdown while a read is in flight.","solutions":["Let the nested run finish; avoid calling loop.stop()/close() while read_database executes","Call read_database from a plain script or thread with no running loop, so the patch is bypassed","Use the async driver natively: await the connector in an async task and build the DataFrame with pl.from_arrow/pl.from_dicts","Upgrade polars — the vendored nest_asyncio2 receives fixes across releases"],"exampleFix":"# before (sync call inside running loop, Jupyter)\ndf = pl.read_database(\"SELECT * FROM t\", connection=async_conn)\n\n# after (await the async driver directly)\ndf = pl.from_arrow(await async_conn.fetch_arrow_table(\"SELECT * FROM t\"))","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    df = pl.read_database(qry, connection=conn)\nexcept RuntimeError as exc:\n    if \"Event loop stopped before Future completed\" in str(exc):\n        # loop was stopped mid-query; retry on a fresh default loop or fail cleanly\n        df = pl.read_database(qry, connection=sync_conn)\n    else:\n        raise","preventionTips":["Do not call loop.stop()/close() while a nested read_database is running","Run read_database outside a live event loop (worker thread or script) when possible","Prefer native async calls (await connector) over the sync bridge in async apps"],"tags":["python","polars","asyncio","event-loop","jupyter","database","runtimeerror"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}