pola-rs/polars · error · ValueError

Can't patch loop of type %s

Error message

Can't patch loop of type %s

What it means

To run async drivers synchronously, polars patches the current event loop with vendored nest_asyncio, which requires an asyncio.BaseEventLoop subclass (it replaces run_forever/run_until_complete/_run_once and swaps _ready). C-implemented loops such as uvloop.Loop do not derive from BaseEventLoop, so apply() raises this ValueError naming the loop type.

Source

Thrown at py-polars/src/polars/_utils/nest_asyncio.py:392

        try:
            self._set_coroutine_origin_tracking(self._debug)
            if self._asyncgens is not None:
                sys.set_asyncgen_hooks(
                    firstiter=self._asyncgen_firstiter_hook,
                    finalizer=self._asyncgen_finalizer_hook,
                )
            yield
        finally:
            self._set_coroutine_origin_tracking(False)
            if self._asyncgens is not None:
                sys.set_asyncgen_hooks(*old_agen_hooks)

    def _check_running(self):
        """Do not throw exception if loop is already running."""
        pass

    if not isinstance(loop, asyncio.BaseEventLoop):
        raise ValueError("Can't patch loop of type %s" % type(loop))
    if not isinstance(loop._ready, _ReentrantReady):
        old_ready, loop._ready = loop._ready, _ReentrantReady()
        while old_ready:
            loop._ready.append(old_ready.popleft())
    if hasattr(loop, "_nest_patched"):
        return
    cls = loop.__class__
    cls.run_forever = run_forever
    cls.run_until_complete = run_until_complete
    cls._run_once = _run_once
    cls._check_running = _check_running
    cls._check_runnung = _check_running  # typo in Python 3.7 source
    cls._num_runs_pending = 1 if loop.is_running() else 0
    cls._is_proactorloop = os.name == "nt" and issubclass(
        cls, asyncio.ProactorEventLoop
    )
    if sys.version_info < (3, 7, 0):
        cls._set_coroutine_origin_tracking = cls._set_coroutine_wrapper

View on GitHub (pinned to df599052da)

Solutions

  1. Use a synchronous database driver/connection for read_database in that process
  2. Run the read in a subprocess or worker with the default policy: asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
  3. Await the async connector yourself and build the DataFrame (pl.from_arrow), avoiding the loop patch entirely

Example fix

# before
uvloop.install()                       # app installed uvloop
df = pl.read_database(qry, connection=conn)  # ValueError: can't patch

# after
df = pl.read_database(qry, connection=sync_conn)  # sync driver path
Defensive patterns

Strategy: type-guard

Validate before calling

import asyncio

loop = asyncio.get_event_loop()
if not isinstance(loop, asyncio.BaseEventLoop):
    raise RuntimeError(f"cannot use async drivers with {type(loop).__name__}; use a sync driver")

Type guard

import asyncio

def is_patchable_loop() -> bool:
    try:
        return isinstance(asyncio.get_event_loop(), asyncio.BaseEventLoop)
    except RuntimeError:
        return True  # no running loop; a fresh default loop will be used

Prevention

When it happens

Trigger: pl.read_database(...) while uvloop is the active loop — installed explicitly via uvloop.install()/asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) or by a web framework (uvicorn, sanic) hosting the code that then calls polars.

Common situations: Async web services (uvloop is the default in many) that also call pl.read_database inline; test harnesses that install uvloop globally for speed.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/0c710a3068712edb. Report an issue: GitHub.