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
- Use `async with coco.runtime():` instead of `with coco.runtime():`
- In notebooks, use the async form (or nest_asyncio only as a last resort)
- 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
- In notebooks always use the async form of context managers
- Keep sync entry points (start_blocking, update_blocking) out of async code paths
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
- coco.use_state() cannot be called inside a `with…
- LiveComponent classes cannot be used with use_mount(). Use…
- LiveMap supports a single active watch() at a time.
- Memo state function returned an awaitable from a sync…
- mount_each() requires a ComponentSubpath when the function…
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)