{"record":{"id":"7c24bf80a055006a","repo":"aio-libs/aiohttp","slug":"module-name-has-no-attribute-name","errorCode":null,"errorMessage":"module {__name__} has no attribute {name}","messagePattern":"module (.+?) has no attribute (.+?)","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"aiohttp/__init__.py","lineNumber":258,"sourceCode":"def __dir__() -> tuple[str, ...]:\n    return __all__ + (\"__doc__\",)\n\n\ndef __getattr__(name: str) -> object:\n    global GunicornUVLoopWebWorker, GunicornWebWorker\n\n    # Importing gunicorn takes a long time (>100ms), so only import if actually needed.\n    if name in (\"GunicornUVLoopWebWorker\", \"GunicornWebWorker\"):\n        try:\n            from .worker import GunicornUVLoopWebWorker as guv, GunicornWebWorker as gw\n        except ImportError:\n            return None\n\n        GunicornUVLoopWebWorker = guv  # type: ignore[misc]\n        GunicornWebWorker = gw  # type: ignore[misc]\n        return guv if name == \"GunicornUVLoopWebWorker\" else gw\n\n    raise AttributeError(f\"module {__name__} has no attribute {name}\")\n","sourceCodeStart":240,"sourceCodeEnd":259,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/__init__.py#L240-L259","documentation":"aiohttp uses a PEP 562 module-level `__getattr__` for lazy imports. Only `GunicornUVLoopWebWorker` and `GunicornWebWorker` are special-cased (loaded on demand, returning `None` if gunicorn is absent). Every other attribute that is not already bound on the package raises `AttributeError`, meaning the requested name is not part of aiohttp's public API.","triggerScenarios":"Any expression of the form `aiohttp.<name>` where `<name>` is neither an imported symbol in `aiohttp/__init__.py` nor one of the two lazy gunicorn worker names. Hits when the name was removed/renamed, is misspelled, or belongs to a private submodule that must be imported directly.","commonSituations":"Upgrading aiohttp (3.x to 4.x) where symbols moved or were removed; copy-pasted snippets referencing old names; IDE autocomplete suggesting a non-exported name; accessing a submodule class via the top package instead of `from aiohttp import web`.","solutions":["Check `aiohttp.__all__` (or the installed version's docs) for the correct public name.","Import the symbol from its real submodule, e.g. `from aiohttp import web` or `from aiohttp.web import Application`.","Pin the aiohttp version your code was written against so removed symbols don't surprise you."],"exampleFix":"// before\nimport aiohttp\nloop = aiohttp.AsyncccResolver()  # typo / removed name -> AttributeError\n// after\nimport aiohttp\nloop = aiohttp.ThreadedResolver()  # valid exported name","handlingStrategy":"validation","validationCode":"import aiohttp\nname = \"Application\"\nassert name in aiohttp.__all__ or hasattr(aiohttp, name), f\"{name} is not exported by aiohttp\"","typeGuard":null,"tryCatchPattern":"try:\n    obj = aiohttp.SomeName\nexcept AttributeError:\n    # fall back to the correct submodule import\n    from aiohttp.web import Application as obj","preventionTips":["Treat `AttributeError` on the top-level package as an API-migration signal, not a runtime quirk.","After upgrading aiohttp, run a static import check (`python -c 'import aiohttp'` plus mypy) before deploying.","Prefer explicit submodule imports over reaching into the package root."],"tags":["api","import","version-migration","attribute-error"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}