{"record":{"id":"db33fc88348a7f4d","repo":"python/cpython","slug":"name-is-not-part-of-stable-abi-document-it-as","errorCode":null,"errorMessage":"{name} is not part of stable ABI. Document it as `c:macro::` rather than `corresponding-type-slot::`.","messagePattern":"(.+?) is not part of stable ABI\\. Document it as `c:macro::` rather than `corresponding-type-slot::`\\.","errorType":"exception","errorClass":"LookupError","httpStatus":null,"severity":"error","filePath":"Doc/tools/extensions/c_annotations.py","lineNumber":428,"sourceCode":"\n    If there is no corresponding field, these should be documented as normal\n    macros.\n    \"\"\"\n\n    has_content = False\n\n    required_arguments = 1\n    optional_arguments = 0\n\n    def run(self) -> list[nodes.Node]:\n        name = self.arguments[0]\n        state = self.env.domaindata[\"c_annotations\"]\n        stable_abi_data = state[\"stable_abi_data\"]\n\n        try:\n            record = stable_abi_data[name]\n        except LookupError as err:\n            raise LookupError(\n                f\"{name} is not part of stable ABI. \"\n                + \"Document it as `c:macro::` rather than \"\n                + \"`corresponding-type-slot::`.\"\n            ) from err\n\n        annotation = _stable_abi_annotation(record, is_corresponding_slot=True)\n\n        node = nodes.paragraph()\n        content = [\n            \".. c:namespace:: NULL\",\n            \"\",\n            \".. c:macro:: \" + name,\n            \"   :no-typesetting:\",\n        ]\n        self.state.nested_parse(StringList(content), 0, node)\n        node.insert(0, annotation)\n        return [node]\n","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Doc/tools/extensions/c_annotations.py#L410-L446","documentation":"asyncio.run() must be the entry point that creates and owns the event loop; it cannot run while a loop is already running in the current thread. The guard uses events._get_running_loop() and deliberately fails fast with a short traceback. Nesting asyncio.run() inside a coroutine is unsupported because the outer loop cannot be suspended behind a second loop.","triggerScenarios":"Calling asyncio.run(...) inside an async def, inside a loop callback, inside a Jupyter notebook cell, or from a thread that is currently running a loop. Also transitively: a sync library function that internally calls asyncio.run() being invoked from async code.","commonSituations":"Jupyter/IPython (running loop) calling libraries that use asyncio.run() for bridging; test code mixing pytest.sync execution with asyncio.run inside fixtures; web frameworks (FastAPI handlers) calling sync SDKs that call asyncio.run(); migration from threads to asyncio where nested entrypoints remain.","solutions":["Inside async code, await the coroutine directly instead of asyncio.run()","Give the library an async API: async def do_async() plus a thin sync wrapper do() = asyncio.run(do_async()) that is only called from sync contexts","In Jupyter, use top-level await or nest_asyncio.apply() as an environment-specific workaround","Restructure so asyncio.run() appears exactly once at the true process entrypoint"],"exampleFix":"# before\nasync def handler():\n    result = asyncio.run(fetch())  # RuntimeError\n# after\nasync def handler():\n    result = await fetch()","handlingStrategy":"validation","validationCode":"import asyncio, asyncio.events as events\n\ndef run_bridge(coro_factory):\n    try:\n        events.get_running_loop()\n    except RuntimeError:\n        return asyncio.run(coro_factory())\n    raise RuntimeError('already inside a loop: await the coroutine instead')","typeGuard":null,"tryCatchPattern":"try:\n    asyncio.run(main())\nexcept RuntimeError as e:\n    if 'running event loop' in str(e):\n        raise RuntimeError('await main() directly here') from e\n    raise","preventionTips":["Keep exactly one asyncio.run() at the process entrypoint","In Jupyter, use top-level await or nest_asyncio deliberately","Audit sync libraries called from async handlers for hidden asyncio.run","Convert library internals to native async coroutines"],"tags":["asyncio","event-loop","nested-loop","entrypoint"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}