{"record":{"id":"65dbba2a06947978","repo":"python/cpython","slug":"capture-call-graph-is-called-outside-of-a-runnin","errorCode":null,"errorMessage":"capture_call_graph() is called outside of a running event loop and no *future* to introspect was provided","messagePattern":"capture_call_graph\\(\\) is called outside of a running event loop and no \\*future\\* to introspect was provided","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"warning","filePath":"Lib/asyncio/graph.py","lineNumber":135,"sourceCode":"    ``abs(limit)`` entries.  If 'limit' is positive, the entries left are\n    the closest to the invocation point.  If 'limit' is negative, the\n    topmost entries are left.  If 'limit' is omitted or None, all entries\n    are present.  If 'limit' is 0, the call stack is not captured at all,\n    only \"awaited by\" information is present.\n    \"\"\"\n\n    loop = events._get_running_loop()\n\n    if future is not None:\n        # Check if we're in a context of a running event loop;\n        # if yes - check if the passed future is the currently\n        # running task or not.\n        if loop is None or future is not tasks.current_task(loop=loop):\n            return _build_graph_for_future(future, limit=limit)\n        # else: future is the current task, move on.\n    else:\n        if loop is None:\n            raise RuntimeError(\n                'capture_call_graph() is called outside of a running '\n                'event loop and no *future* to introspect was provided')\n        future = tasks.current_task(loop=loop)\n\n    if future is None:\n        # This isn't a generic call stack introspection utility. If we\n        # can't determine the current task and none was provided, we\n        # just return.\n        return None\n\n    if not isinstance(future, futures.Future):\n        raise TypeError(\n            f\"{future!r} object does not appear to be compatible \"\n            f\"with asyncio.Future\"\n        )\n\n    call_stack: list[FrameCallGraphEntry] = []\n","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/graph.py#L117-L153","documentation":"asyncio.graph.capture_call_graph() introspects the current running task's call stack. Without a future argument it needs a running event loop to find tasks.current_task(); called from synchronous code it raises this RuntimeError telling you to either call it inside the loop or pass an explicit future to introspect.","triggerScenarios":"Calling capture_call_graph() from a plain function during import, from a thread, or after the loop stopped, without the future parameter.","commonSituations":"Diagnostics/error reporters hooked into sync exception handlers; logging pipelines that try to attach asyncio context; calling from __del__ or signal handlers.","solutions":["Call capture_call_graph() from inside a coroutine/callback running on the loop","Or pass future=<the Task/Future under inspection> explicitly","Capture the graph eagerly while the task is alive, store it, and report later from sync code"],"exampleFix":"# before\ndef sync_error_handler():\n    g = asyncio.graph.capture_call_graph()  # RuntimeError\n\n# after\nasync def task_body():\n    g = asyncio.graph.capture_call_graph()  # inside running loop\ndef sync_error_handler(saved_graph):\n    report(saved_graph)","handlingStrategy":"validation","validationCode":"import asyncio\nif asyncio.events._get_running_loop() is None and future is None:\n    # no loop and no future: capture_call_graph() will raise\n    graph = None","typeGuard":"def can_capture_call_graph(future=None) -> bool:\n    import asyncio\n    return future is not None or asyncio.events._get_running_loop() is not None","tryCatchPattern":null,"preventionTips":["Call capture_call_graph() from inside coroutines","Or pass the target future explicitly","Capture graphs eagerly while tasks are alive; report later"],"tags":["asyncio","debugging","event-loop","introspection"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}