{"record":{"id":"0611b1223f0d75fb","repo":"python/cpython","slug":"obj-r-does-not-have-annotations","errorCode":null,"errorMessage":"{obj!r} does not have annotations","messagePattern":"(.+?) does not have annotations","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/annotationlib.py","lineNumber":1003,"sourceCode":"                ann = _get_dunder_annotations(obj)\n        case Format.STRING:\n            # For STRING, we try to call __annotate__\n            ann = _get_and_call_annotate(obj, format)\n            if ann is not None:\n                return dict(ann)\n            # But if we didn't get it, we use __annotations__ instead.\n            ann = _get_dunder_annotations(obj)\n            if ann is not None:\n                return annotations_to_string(ann)\n        case Format.VALUE_WITH_FAKE_GLOBALS:\n            raise ValueError(\"The VALUE_WITH_FAKE_GLOBALS format is for internal use only\")\n        case _:\n            raise ValueError(f\"Unsupported format {format!r}\")\n\n    if ann is None:\n        if isinstance(obj, type) or callable(obj):\n            return {}\n        raise TypeError(f\"{obj!r} does not have annotations\")\n\n    if not ann:\n        return {}\n\n    if not eval_str:\n        return dict(ann)\n\n    if globals is None or locals is None:\n        if isinstance(obj, type):\n            # class\n            obj_globals = None\n            module_name = getattr(obj, \"__module__\", None)\n            if module_name:\n                module = sys.modules.get(module_name, None)\n                if module:\n                    obj_globals = getattr(module, \"__dict__\", None)\n            obj_locals = dict(vars(obj))\n            unwrap = obj","sourceCodeStart":985,"sourceCodeEnd":1021,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/annotationlib.py#L985-L1021","documentation":"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.","triggerScenarios":"get_annotations(42); get_annotations(some_instance); get_annotations(<module without __annotations__>); passing an instance instead of its class.","commonSituations":"Introspection tools walking arbitrary objects; passing an instance where the class was intended; objects whose __annotations__ was deleted or set to None.","solutions":["Pass the class or function itself, not an instance: get_annotations(type(obj)).","Check `callable(obj) or isinstance(obj, type)` before calling, or use getattr checks.","Catch TypeError and treat it as 'no annotations'."],"exampleFix":"# before\nann = get_annotations(instance)  # TypeError: 42 does not have annotations\n\n# after\nann = get_annotations(type(instance)) or {}","handlingStrategy":"type-guard","validationCode":"def has_annotations_source(obj) -> bool:\n    return (isinstance(obj, type) or callable(obj)\n            or getattr(obj, '__annotations__', None) is not None\n            or getattr(obj, '__annotate__', None) is not None)","typeGuard":"def annotatable(obj) -> bool:\n    return isinstance(obj, type) or callable(obj)","tryCatchPattern":"try:\n    ann = get_annotations(obj)\nexcept TypeError as e:\n    if 'does not have annotations' in str(e):\n        ann = {}\n    else:\n        raise","preventionTips":["Pass classes/functions, not instances","Use type(obj) when handed an instance","Treat 'no annotations' as an empty dict in callers"],"tags":["python","annotations","typeerror","introspection"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}