cocoindex-io/cocoindex · error · RuntimeError

Cannot use sync 'with coco.runtime()' from within an async…

Error message

Cannot use sync 'with coco.runtime()' from within an async event loop. Use 'async with coco.runtime()' instead.

What it means

coco.runtime() supports both sync and async context-manager forms. The sync __enter__ calls start_blocking(), which cannot run inside a running asyncio event loop (it blocks the loop), so it detects a running loop and raises immediately with the correct alternative.

Solutions

  1. Use `async with coco.runtime():` instead of `with coco.runtime():`
  2. In notebooks, use the async form (or nest_asyncio only as a last resort)
  3. Move the sync usage to plain non-async script code where no loop is running

Example fix

// before
with coco.runtime():
    app.update_blocking()
// after
async with coco.runtime():
    await app.update()
Defensive patterns

Strategy: type-guard

Validate before calling

import asyncio
if asyncio.get_running_loop() is not None:  # inside running loop
    ...  # use async form
# usage
if _in_loop():
    async with coco.runtime():
        ...
else:
    with coco.runtime():
        ...

Type guard

def in_async_loop() -> bool:
    try:
        asyncio.get_running_loop()
        return True
    except RuntimeError:
        return False

Try / catch

try:
    with coco.runtime():
        ...
except RuntimeError as e:
    if "async event loop" in str(e):
        raise  # switch call site to `async with coco.runtime()`

Prevention

When it happens

Trigger: Using `with coco.runtime():` inside an async def function or any code running on an asyncio event loop (e.g. inside a Jupyter notebook with an active loop, or an async app).

Common situations: Jupyter/IPython notebooks where a loop is always running; calling sync-style runtime setup inside async test code; copy-pasting sync examples into async apps.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/ccf07ec0b676014a. Report an issue: GitHub.

Appendix: source

Thrown at python/cocoindex/_internal/api.py:709

    """Stop the default environment synchronously (and exit its lifespan, if any)."""
    environment.stop_sync()


async def default_env() -> environment.Environment:
    """Get the default environment (starting it if needed)."""
    return await environment.start()


class _DualModeRuntime:
    """Context manager that works with both `with` and `async with`."""

    def __enter__(self) -> None:
        try:
            asyncio.get_running_loop()
        except RuntimeError:
            pass  # No running loop — sync usage is fine
        else:
            raise RuntimeError(
                "Cannot use sync 'with coco.runtime()' from within an async event loop. "
                "Use 'async with coco.runtime()' instead."
            )
        start_blocking()
        return None

    def __exit__(self, *exc: Any) -> None:
        stop_blocking()

    async def __aenter__(self) -> None:
        await start()
        return None

    async def __aexit__(self, *exc: Any) -> None:
        await stop()


def runtime() -> _DualModeRuntime:

View on GitHub (pinned to e84aa99b32)