aio-libs/aiohttp · error · RuntimeError

Failed to get module name.

Error message

Failed to get module name.

What it means

BaseKey.__init__ raises RuntimeError when it cannot find a '<module>' frame in the call stack by walking frame.f_back. BaseKey (and its subclass AppKey) prefixes its internal name with the calling module's __name__ for deduplication. If instantiated from a context with no module-level frame (e.g. a deeply nested call where the module frame has been optimized away), the loop exits without breaking and the else clause fires.

Solutions

  1. Define AppKey instances at module level in a .py file (the normal use case)
  2. If using exec/eval, ensure the code object has a '<module>' frame by providing a proper __name__ in globals
  3. Avoid creating AppKey dynamically in nested function calls — define them at module scope

Example fix

# before (dynamic creation may fail)
key = eval('AppKey("my_key")')

# after (module-level definition)
# myapp/keys.py
from aiohttp.web import AppKey
my_key = AppKey('my_key', str)
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def can_resolve_module_name() -> bool:
    frame = inspect.currentframe()
    while frame:
        if frame.f_code.co_name == '<module>':
            return True
        frame = frame.f_back
    return False

if not can_resolve_module_name():
    raise RuntimeError('Cannot create AppKey: no module frame in call stack')

Try / catch

try:
    my_key = AppKey('my_key', str)
except RuntimeError as e:
    if 'Failed to get module name' in str(e):
        # Define at module level instead of dynamically
        raise RuntimeError('AppKey must be defined at module level')
    raise

Prevention

When it happens

Trigger: Creating an AppKey or BaseKey from a context where inspect.currentframe() and walking f_back cannot reach a frame with co_name == '<module>'. This can happen in certain REPL environments, eval/exec contexts, or when frame introspection is limited by the Python implementation (e.g. some JIT or restricted environments).

Common situations: Defining AppKey instances in interactive REPL sessions where the module frame structure differs; using exec() to dynamically define keys; running under Python implementations with limited frame support; deeply nested class bodies where frame walking misses the module frame.

Related errors


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

Appendix: source

Thrown at aiohttp/helpers.py:917

    __slots__ = ("_name", "_t", "__orig_class__")

    # This may be set by Python when instantiating with a generic type. We need to
    # support this, in order to support types that are not concrete classes,
    # like Iterable, which can't be passed as the second parameter to __init__.
    __orig_class__: type[object]

    # TODO(PY314): Change Type to TypeForm (this should resolve unreachable below).
    def __init__(self, name: str, t: type[_T] | None = None):
        # Prefix with module name to help deduplicate key names.
        frame = inspect.currentframe()
        while frame:
            if frame.f_code.co_name == "<module>":
                module: str = frame.f_globals["__name__"]
                break
            frame = frame.f_back
        else:
            raise RuntimeError("Failed to get module name.")

        # https://github.com/python/mypy/issues/14209
        self._name = module + "." + name  # type: ignore[possibly-undefined]
        self._t = t

    def __lt__(self, other: object) -> bool:
        if isinstance(other, BaseKey):
            return self._name < other._name
        return True  # Order BaseKey above other types.

    def __repr__(self) -> str:
        t = self._t
        if t is None:
            with suppress(AttributeError):
                # Set to type arg.
                t = get_args(self.__orig_class__)[0]

        if t is None:

View on GitHub (pinned to d041d4d0fd)