pola-rs/polars · error · RuntimeError
Event loop stopped before Future completed.
Error message
Event loop stopped before Future completed.
What it means
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.
Source
Thrown at py-polars/src/polars/_utils/nest_asyncio.py:283
def run_forever(self):
with manage_run(self), manage_asyncgens(self):
while True:
self._run_once()
if self._stopping:
break
self._stopping = False
def run_until_complete(self, future):
with manage_run(self):
f = asyncio.ensure_future(future, loop=self)
if f is not future:
f._log_destroy_pending = False
while not f.done():
self._run_once()
if self._stopping:
break
if not f.done():
raise RuntimeError("Event loop stopped before Future completed.")
return f.result()
def _run_once(self):
"""
Simplified re-implementation of asyncio's _run_once that
runs handles as they become ready.
"""
scheduled = self._scheduled
while scheduled and scheduled[0]._cancelled:
heappop(scheduled)
timeout = (
0
if self._ready or self._stopping
else min(max(scheduled[0]._when - self.time(), 0), 86400)
if scheduled
else None
)View on GitHub (pinned to df599052da)
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
Example fix
# before (sync call inside running loop, Jupyter)
df = pl.read_database("SELECT * FROM t", connection=async_conn)
# after (await the async driver directly)
df = pl.from_arrow(await async_conn.fetch_arrow_table("SELECT * FROM t")) Defensive patterns
Strategy: try-catch
Try / catch
try:
df = pl.read_database(qry, connection=conn)
except RuntimeError as exc:
if "Event loop stopped before Future completed" in str(exc):
# loop was stopped mid-query; retry on a fresh default loop or fail cleanly
df = pl.read_database(qry, connection=sync_conn)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Can't patch loop of type %s
- {result}
- cannot select columns using key of type {qualified_type_name
- expected {df.width} values when selecting columns by boolean
- index {key} is out of bounds for DataFrame of height {num_ro
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/9e76dddd7d7c6439.
Report an issue: GitHub.