python/cpython · error · TypeError

{obj!r} does not have annotations

Error message

{obj!r} does not have annotations

What it means

After trying __annotations__ and __annotate__, get_annotations() raises TypeError if no annotations were found AND the object is neither a class nor callable. Classes and callables get an empty dict as a courtesy; everything else (instances, modules without annotations, plain objects) is considered not annotatable, hence the TypeError.

Source

Thrown at Lib/annotationlib.py:1003

                ann = _get_dunder_annotations(obj)
        case Format.STRING:
            # For STRING, we try to call __annotate__
            ann = _get_and_call_annotate(obj, format)
            if ann is not None:
                return dict(ann)
            # But if we didn't get it, we use __annotations__ instead.
            ann = _get_dunder_annotations(obj)
            if ann is not None:
                return annotations_to_string(ann)
        case Format.VALUE_WITH_FAKE_GLOBALS:
            raise ValueError("The VALUE_WITH_FAKE_GLOBALS format is for internal use only")
        case _:
            raise ValueError(f"Unsupported format {format!r}")

    if ann is None:
        if isinstance(obj, type) or callable(obj):
            return {}
        raise TypeError(f"{obj!r} does not have annotations")

    if not ann:
        return {}

    if not eval_str:
        return dict(ann)

    if globals is None or locals is None:
        if isinstance(obj, type):
            # class
            obj_globals = None
            module_name = getattr(obj, "__module__", None)
            if module_name:
                module = sys.modules.get(module_name, None)
                if module:
                    obj_globals = getattr(module, "__dict__", None)
            obj_locals = dict(vars(obj))
            unwrap = obj

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass the class or function itself, not an instance: get_annotations(type(obj)).
  2. Check `callable(obj) or isinstance(obj, type)` before calling, or use getattr checks.
  3. Catch TypeError and treat it as 'no annotations'.

Example fix

# before
ann = get_annotations(instance)  # TypeError: 42 does not have annotations

# after
ann = get_annotations(type(instance)) or {}
Defensive patterns

Strategy: type-guard

Validate before calling

def has_annotations_source(obj) -> bool:
    return (isinstance(obj, type) or callable(obj)
            or getattr(obj, '__annotations__', None) is not None
            or getattr(obj, '__annotate__', None) is not None)

Type guard

def annotatable(obj) -> bool:
    return isinstance(obj, type) or callable(obj)

Try / catch

try:
    ann = get_annotations(obj)
except TypeError as e:
    if 'does not have annotations' in str(e):
        ann = {}
    else:
        raise

Prevention

When it happens

Trigger: get_annotations(42); get_annotations(some_instance); get_annotations(<module without __annotations__>); passing an instance instead of its class.

Common situations: Introspection tools walking arbitrary objects; passing an instance where the class was intended; objects whose __annotations__ was deleted or set to None.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/0611b1223f0d75fb. Report an issue: GitHub.