{"record":{"id":"1940c7be6b3c3c4d","repo":"python/cpython","slug":"cannot-subclass-forwardref","errorCode":null,"errorMessage":"Cannot subclass ForwardRef","messagePattern":"Cannot subclass ForwardRef","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/annotationlib.py","lineNumber":101,"sourceCode":"        self.__forward_is_class__ = is_class\n        self.__forward_module__ = module\n        self.__owner__ = owner\n        # These are always set to None here but may be non-None if a ForwardRef\n        # is created through __class__ assignment on a _Stringifier object.\n        self.__globals__ = None\n        # This may be either a cell object (for a ForwardRef referring to a single name)\n        # or a dict mapping cell names to cell objects (for a ForwardRef containing references\n        # to multiple names).\n        self.__cell__ = None\n        self.__extra_names__ = None\n        # These are initially None but serve as a cache and may be set to a non-None\n        # value later.\n        self.__code__ = None\n        self.__ast_node__ = None\n        self.__resolved_str_cache__ = None\n\n    def __init_subclass__(cls, /, *args, **kwds):\n        raise TypeError(\"Cannot subclass ForwardRef\")\n\n    def evaluate(\n        self,\n        *,\n        globals=None,\n        locals=None,\n        type_params=None,\n        owner=None,\n        format=Format.VALUE,\n    ):\n        \"\"\"Evaluate the forward reference and return the value.\n\n        If the forward reference cannot be evaluated, raise an exception.\n        \"\"\"\n        match format:\n            case Format.STRING:\n                return self.__resolved_str__\n            case Format.VALUE:","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/annotationlib.py#L83-L119","documentation":"ForwardRef sets __init_subclass__ to unconditionally raise TypeError('Cannot subclass ForwardRef'). The class is treated as a final implementation detail of the annotation machinery, so subclassing to tweak evaluation is disallowed.","triggerScenarios":"class MyRef(ForwardRef): ... — at class-creation time (instance creation never happens), __init_subclass__ fires and raises.","commonSituations":"Libraries trying to subclass ForwardRef to add lazy caching or custom name resolution (a pattern that worked with older typing internals); porting typing-extension code to Python 3.14's annotationlib.","solutions":["Wrap instead of subclass: hold a ForwardRef instance in your own class and delegate .evaluate()","Customize evaluation by passing globals/locals/owner/type_params to ForwardRef.evaluate()","For custom annotation semantics, implement __annotations__ via AnnotationArray/_AnnotatedAlias-style composition instead of inheritance"],"exampleFix":"# before\nclass MyRef(ForwardRef):  # TypeError: Cannot subclass ForwardRef\n    pass\n\n# after\nclass MyRef:\n    def __init__(self, ref: str):\n        self._ref = ForwardRef(ref)\n    def evaluate(self, **kw):\n        return self._ref.evaluate(**kw)","handlingStrategy":"type-guard","validationCode":"from annotationlib import ForwardRef\n\ndef is_final(cls) -> bool:\n    return getattr(cls, '__init_subclass__', None) is not None and 'Cannot subclass' in getattr(cls.__init_subclass__, '__doc__' if False else '', '') or cls is ForwardRef","typeGuard":"from annotationlib import ForwardRef\n\ndef can_subclass(base) -> bool:\n    try:\n        type('Probe', (base,), {})\n        return True\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    class MyRef(ForwardRef):\n        pass\nexcept TypeError:\n    class MyRef:  # delegation fallback\n        def __init__(self, ref):\n            self._ref = ForwardRef(ref)","preventionTips":["Treat ForwardRef as final; customize via evaluate() arguments, not inheritance","Wrap-and-delegate when you need extra behavior","Pin against annotationlib in CI so upstream finality changes surface early"],"tags":["annotations","typing","forwardref","subclassing","cpython"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}