{"record":{"id":"ccf07ec0b676014a","repo":"cocoindex-io/cocoindex","slug":"cannot-use-sync-with-coco-runtime-from-within","errorCode":null,"errorMessage":"Cannot use sync 'with coco.runtime()' from within an async event loop. Use 'async with coco.runtime()' instead.","messagePattern":"Cannot use sync 'with coco\\.runtime\\(\\)' from within an async event loop\\. Use 'async with coco\\.runtime\\(\\)' instead\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/api.py","lineNumber":709,"sourceCode":"    \"\"\"Stop the default environment synchronously (and exit its lifespan, if any).\"\"\"\n    environment.stop_sync()\n\n\nasync def default_env() -> environment.Environment:\n    \"\"\"Get the default environment (starting it if needed).\"\"\"\n    return await environment.start()\n\n\nclass _DualModeRuntime:\n    \"\"\"Context manager that works with both `with` and `async with`.\"\"\"\n\n    def __enter__(self) -> None:\n        try:\n            asyncio.get_running_loop()\n        except RuntimeError:\n            pass  # No running loop — sync usage is fine\n        else:\n            raise RuntimeError(\n                \"Cannot use sync 'with coco.runtime()' from within an async event loop. \"\n                \"Use 'async with coco.runtime()' instead.\"\n            )\n        start_blocking()\n        return None\n\n    def __exit__(self, *exc: Any) -> None:\n        stop_blocking()\n\n    async def __aenter__(self) -> None:\n        await start()\n        return None\n\n    async def __aexit__(self, *exc: Any) -> None:\n        await stop()\n\n\ndef runtime() -> _DualModeRuntime:","sourceCodeStart":691,"sourceCodeEnd":727,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/api.py#L691-L727","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nwith coco.runtime():\n    app.update_blocking()\n// after\nasync with coco.runtime():\n    await app.update()","handlingStrategy":"type-guard","validationCode":"import asyncio\nif asyncio.get_running_loop() is not None:  # inside running loop\n    ...  # use async form\n# usage\nif _in_loop():\n    async with coco.runtime():\n        ...\nelse:\n    with coco.runtime():\n        ...","typeGuard":"def in_async_loop() -> bool:\n    try:\n        asyncio.get_running_loop()\n        return True\n    except RuntimeError:\n        return False","tryCatchPattern":"try:\n    with coco.runtime():\n        ...\nexcept RuntimeError as e:\n    if \"async event loop\" in str(e):\n        raise  # switch call site to `async with coco.runtime()`","preventionTips":["In notebooks always use the async form of context managers","Keep sync entry points (start_blocking, update_blocking) out of async code paths"],"tags":["python","asyncio","api-misuse"],"backgroundTag":"unsupported-operation","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}