{"record":{"id":"8aefc1f14a00b37c","repo":"supermemoryai/supermemory","slug":"cannot-save-memory-in-sync-client-from-async-conte","errorCode":null,"errorMessage":"Cannot save memory in sync client from async context","messagePattern":"Cannot save memory in sync client from async context","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/openai-sdk-python/src/supermemory_openai/middleware.py","lineNumber":460,"sourceCode":"                    if self._options.custom_id\n                    else None\n                )\n\n                # Use asyncio.run() for the memory addition\n                try:\n                    asyncio.run(\n                        add_memory_tool(\n                            self._supermemory_client,\n                            self._container_tag,\n                            content,\n                            custom_id,\n                            self._logger,\n                        )\n                    )\n                except RuntimeError as e:\n                    if \"cannot be called from a running event loop\" in str(e):\n                        # We're in an async context, log warning and skip memory saving\n                        self._logger.warn(\n                            \"Cannot save memory in sync client from async context\",\n                            {\"error\": str(e)},\n                        )\n                    else:\n                        raise\n                except SupermemoryNetworkError as e:\n                    # Network errors are expected, log as warning\n                    self._logger.warn(\"Network error saving memory\", {\"error\": str(e)})\n                except (SupermemoryAPIError, SupermemoryMemoryOperationError) as e:\n                    # API/memory errors are concerning, log as error\n                    self._logger.error(\"Failed to save memory\", {\"error\": str(e)})\n                except Exception as e:\n                    # Unexpected errors should be investigated\n                    self._logger.error(\n                        \"Unexpected error saving memory\",\n                        {\"error\": str(e), \"type\": type(e).__name__},\n                    )\n","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/supermemoryai/supermemory/blob/d436792e777a99865939dd543c8d1a16d57f54ec/packages/openai-sdk-python/src/supermemory_openai/middleware.py#L442-L478","documentation":"This warning is logged when a synchronous OpenAI client wrapped by Supermemory's middleware tries to save memories, but the call happens inside a running asyncio event loop. The middleware detects the classic RuntimeError ('cannot be called from a running event loop') and degrades gracefully by skipping the memory save instead of crashing. Memory persistence for that request is silently lost.","triggerScenarios":"Calling create_with_memory (or chat.completions.create through the sync wrapped client) from inside an async function or a framework with a running loop (Jupyter, FastAPI handler calling blocking SDK code, anyio/asyncio.to_thread offloading back into async). The sync save path uses asyncio.run()/loop.run_until_complete internally, which is illegal while a loop is already running.","commonSituations":"Using the sync Supermemory-wrapped OpenAI client inside Jupyter notebooks (which always run an event loop), calling it from FastAPI/Starlette async endpoints, or migrating sync code into an async app without switching to AsyncOpenAI. Versions of the middleware that added background memory saving to the sync client exposed this.","solutions":["Switch to the async client (AsyncOpenAI + create_with_memory await) anywhere a loop is running","Run the sync call in a genuinely separate thread with no loop, e.g. asyncio.to_thread or a worker, so no event loop is active","If losing memory saves in this path is unacceptable, call the Supermemory memories API directly from async code instead of relying on the sync middleware","Upgrade the SDK; check changelog for improved sync-from-async handling"],"exampleFix":"// before\nclient = SupermemoryOpenAI(OpenAI())\nasync def handler():\n    res = client.chat.completions.create_with_memory(...)  # warns, memory lost\n\n// after\nclient = SupermemoryOpenAI(AsyncOpenAI())\nasync def handler():\n    res = await client.chat.completions.create_with_memory(...)","handlingStrategy":"fallback","validationCode":"import asyncio\ntry:\n    asyncio.get_running_loop()\n    in_loop = True\nexcept RuntimeError:\n    in_loop = False\n# choose sync client only when in_loop is False","typeGuard":"def has_running_loop() -> bool:\n    try:\n        asyncio.get_running_loop()\n        return True\n    except RuntimeError:\n        return False","tryCatchPattern":null,"preventionTips":["Always use the AsyncOpenAI-based client inside async functions and notebooks","Route sync SDK calls through asyncio.to_thread only when no loop is needed in that thread","Monitor logs for this warning to catch silent memory-loss in production"],"tags":["python","async","sync-async-bridge","event-loop","memory-save"],"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"}