aio-libs/aiohttp · error · AttributeError

module has no attribute

Error message

module {__name__} has no attribute {name}

What it means

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.

Solutions

  1. Check `aiohttp.__all__` (or the installed version's docs) for the correct public name.
  2. Import the symbol from its real submodule, e.g. `from aiohttp import web` or `from aiohttp.web import Application`.
  3. Pin the aiohttp version your code was written against so removed symbols don't surprise you.

Example fix

// before
import aiohttp
loop = aiohttp.AsyncccResolver()  # typo / removed name -> AttributeError
// after
import aiohttp
loop = aiohttp.ThreadedResolver()  # valid exported name
Defensive patterns

Strategy: validation

Validate before calling

import aiohttp
name = "Application"
assert name in aiohttp.__all__ or hasattr(aiohttp, name), f"{name} is not exported by aiohttp"

Try / catch

try:
    obj = aiohttp.SomeName
except AttributeError:
    # fall back to the correct submodule import
    from aiohttp.web import Application as obj

Prevention

When it happens

Trigger: 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.

Common situations: 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`.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/7c24bf80a055006a. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/__init__.py:258

def __dir__() -> tuple[str, ...]:
    return __all__ + ("__doc__",)


def __getattr__(name: str) -> object:
    global GunicornUVLoopWebWorker, GunicornWebWorker

    # Importing gunicorn takes a long time (>100ms), so only import if actually needed.
    if name in ("GunicornUVLoopWebWorker", "GunicornWebWorker"):
        try:
            from .worker import GunicornUVLoopWebWorker as guv, GunicornWebWorker as gw
        except ImportError:
            return None

        GunicornUVLoopWebWorker = guv  # type: ignore[misc]
        GunicornWebWorker = gw  # type: ignore[misc]
        return guv if name == "GunicornUVLoopWebWorker" else gw

    raise AttributeError(f"module {__name__} has no attribute {name}")

View on GitHub (pinned to d041d4d0fd)