{"record":{"id":"1f080fe960db0063","repo":"supermemoryai/supermemory","slug":"cannot-wait-for-background-tasks-in-sync-context-f","errorCode":null,"errorMessage":"Cannot wait for background tasks in sync context from async environment. Use async context manager or call wait_for_background_tasks() manually.","messagePattern":"Cannot wait for background tasks in sync context from async environment\\. Use async context manager or call wait_for_background_tasks\\(\\) manually\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/openai-sdk-python/src/supermemory_openai/middleware.py","lineNumber":604,"sourceCode":"        try:\n            await self.wait_for_background_tasks(timeout=5.0)\n        except asyncio.TimeoutError:\n            self._logger.warn(\"Some background memory tasks did not complete on exit\")\n\n    def __enter__(self):\n        \"\"\"Sync context manager entry.\"\"\"\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        \"\"\"Sync context manager exit - attempt to wait for background tasks.\"\"\"\n        if self._background_tasks:\n            try:\n                # Try to wait for background tasks in sync context\n                asyncio.run(self.wait_for_background_tasks(timeout=5.0))\n            except RuntimeError as e:\n                if \"cannot be called from a running event loop\" in str(e):\n                    # In async context, just cancel the tasks\n                    self._logger.warn(\n                        \"Cannot wait for background tasks in sync context from async environment. \"\n                        \"Use async context manager or call wait_for_background_tasks() manually.\"\n                    )\n                    self.cancel_background_tasks()\n                else:\n                    raise\n            except asyncio.TimeoutError:\n                self._logger.warn(\n                    \"Some background memory tasks did not complete on exit\"\n                )\n                self.cancel_background_tasks()\n\n    def __getattr__(self, name: str) -> Any:\n        \"\"\"Delegate all other attributes to the wrapped client.\"\"\"\n        return getattr(self._client, name)\n\n\ndef with_supermemory(","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/supermemoryai/supermemory/blob/d436792e777a99865939dd543c8d1a16d57f54ec/packages/openai-sdk-python/src/supermemory_openai/middleware.py#L586-L622","documentation":"Logged when the sync context manager __exit__ tries asyncio.run(wait_for_background_tasks(...)) but an event loop is already running in the current thread (the standard 'asyncio.run() cannot be called from a running event loop' RuntimeError). The middleware cancels all background tasks as a safe fallback, meaning pending memory saves are discarded.","triggerScenarios":"Using 'with wrapped_sync_client:' inside an async environment — Jupyter notebooks, IPython, or sync code invoked from an async framework (FastAPI runs sync handlers in a thread, but libraries like nest_asyncio or direct calls from coroutines trigger it). __exit__ calls asyncio.run, which is illegal with a live loop.","commonSituations":"Notebook usage of the sync client with a context manager; sync SDK calls made from async application code; nest_asyncio environments. The workaround is to manage draining manually or use the async client.","solutions":["Use the async client (AsyncOpenAI) with 'async with' in async environments","Avoid the sync context manager under a running loop; call wait_for_background_tasks() manually from async code and skip __exit__ draining","Drain tasks yourself before exit: run 'await client.wait_for_background_tasks(timeout=5)' inside the loop, then exit the context","If you must nest loops, use nest_asyncio.apply() — but prefer the async client"],"exampleFix":"# before\nwith SupermemoryOpenAI(OpenAI()) as client:  # inside Jupyter/async env\n    client.chat.completions.create_with_memory(...)\n\n# after\nclient = SupermemoryOpenAI(AsyncOpenAI())\nasync with client:\n    await client.chat.completions.create_with_memory(...)","handlingStrategy":"validation","validationCode":"import asyncio\ntry:\n    asyncio.get_running_loop()\n    # use async client + 'async with'\nexcept RuntimeError:\n    pass  # sync 'with' is safe here","typeGuard":"def in_async_context() -> bool:\n    try:\n        asyncio.get_running_loop()\n        return True\n    except RuntimeError:\n        return False","tryCatchPattern":null,"preventionTips":["Never use the sync context manager in Jupyter or async frameworks","Prefer the async client anywhere an event loop may exist","Drain tasks manually via await wait_for_background_tasks() before exit"],"tags":["python","sync-async-bridge","event-loop","context-manager","cancellation"],"backgroundTag":"sync-call-inside-running-event-loop","analyzedSha":"d436792e777a99865939dd543c8d1a16d57f54ec","analyzedAt":"2026-08-28T18:04:46.947Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}