python/cpython · error · TypeError
Cannot subclass ForwardRef
Error message
Cannot subclass ForwardRef
What it means
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.
Source
Thrown at Lib/annotationlib.py:101
self.__forward_is_class__ = is_class
self.__forward_module__ = module
self.__owner__ = owner
# These are always set to None here but may be non-None if a ForwardRef
# is created through __class__ assignment on a _Stringifier object.
self.__globals__ = None
# This may be either a cell object (for a ForwardRef referring to a single name)
# or a dict mapping cell names to cell objects (for a ForwardRef containing references
# to multiple names).
self.__cell__ = None
self.__extra_names__ = None
# These are initially None but serve as a cache and may be set to a non-None
# value later.
self.__code__ = None
self.__ast_node__ = None
self.__resolved_str_cache__ = None
def __init_subclass__(cls, /, *args, **kwds):
raise TypeError("Cannot subclass ForwardRef")
def evaluate(
self,
*,
globals=None,
locals=None,
type_params=None,
owner=None,
format=Format.VALUE,
):
"""Evaluate the forward reference and return the value.
If the forward reference cannot be evaluated, raise an exception.
"""
match format:
case Format.STRING:
return self.__resolved_str__
case Format.VALUE:View on GitHub (pinned to bc6749cc3b)
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
Example fix
# before
class MyRef(ForwardRef): # TypeError: Cannot subclass ForwardRef
pass
# after
class MyRef:
def __init__(self, ref: str):
self._ref = ForwardRef(ref)
def evaluate(self, **kw):
return self._ref.evaluate(**kw) Defensive patterns
Strategy: type-guard
Validate before calling
from annotationlib import ForwardRef
def is_final(cls) -> bool:
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 Type guard
from annotationlib import ForwardRef
def can_subclass(base) -> bool:
try:
type('Probe', (base,), {})
return True
except TypeError:
return False Try / catch
try:
class MyRef(ForwardRef):
pass
except TypeError:
class MyRef: # delegation fallback
def __init__(self, ref):
self._ref = ForwardRef(ref) Prevention
- 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
When it happens
Trigger: class MyRef(ForwardRef): ... — at class-creation time (instance creation never happens), __init_subclass__ fires and raises.
Common situations: 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.
Related errors
- Forward reference must be a string -- got {arg!r}
- name '{name:.200}' is not defined
- Forward reference must be an expression -- got {arg!r}
- Callable must be used as Callable[[arg, ...], result].
- Expected a list of types, an ellipsis, ParamSpec, or Concate
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/1940c7be6b3c3c4d.
Report an issue: GitHub.