reflex-dev/reflex · error · TypeError

Cannot use cached_property on a class without __set_name__.

Error message

Cannot use cached_property on a class without __set_name__.

What it means

A cached_property only knows which instance attribute to cache into after __set_name__ runs at class-definition time. Accessing the property on an instance before __set_name__ was called (or when the descriptor was never assigned inside a class body) leaves _attrname None and this Reflex copy of functools.cached_property raises TypeError. Reflex uses this mechanism for caching ComputedVar values on State instances.

Source

Thrown at packages/reflex-base/src/reflex_base/vars/base.py:2068

            )
            raise TypeError(msg)

    def __get__(self, instance: Any, owner: type | None = None):
        """Get the cached property.

        Args:
            instance: The instance to get the cached property from.
            owner: The owner of the cached property.

        Returns:
            The cached property.

        Raises:
            TypeError: If the class does not have __set_name__.
        """
        if self._attrname is None:
            msg = "Cannot use cached_property on a class without __set_name__."
            raise TypeError(msg)
        cached_field_name = "_reflex_cache_" + self._attrname
        try:
            unique_id = object.__getattribute__(instance, cached_field_name)
        except AttributeError:
            unique_id = uuid.uuid4().int
            object.__setattr__(instance, cached_field_name, unique_id)
        if unique_id not in GLOBAL_CACHE:
            GLOBAL_CACHE[unique_id] = self._func(instance)
        return GLOBAL_CACHE[unique_id]


cached_property_no_lock = cached_property


class VarProtocol(Protocol):
    """A protocol for Var."""

    __dataclass_fields__: ClassVar[dict[str, dataclasses.Field[Any]]]

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Assign the descriptor inside a class body (or call prop.__set_name__(cls, 'attr_name') manually after dynamic assignment)
  2. Use a plain property or a normal instance cache field instead of cached_property for dynamically attached attributes
  3. Prefer defining ComputedVars declaratively in the State class rather than attaching them programmatically

Example fix

# before
prop = _cached_property(fget)
setattr(MyState, 'value', prop)  # __set_name__ never runs
MyState().value  # TypeError

# after
prop = _cached_property(fget)
setattr(MyState, 'value', prop)
prop.__set_name__(MyState, 'value')  # manually finish initialization
Defensive patterns

Strategy: validation

Validate before calling

def attach_prop(cls, prop, name: str):
    setattr(cls, name, prop)
    if getattr(prop, '_attrname', None) is None:
        prop.__set_name__(cls, name)  # ensure cached_property is initialized

Type guard

def is_initialized_cached_property(prop) -> bool:
    return getattr(prop, '_attrname', None) is not None

Try / catch

try:
    value = instance.some_prop
except TypeError as e:
    if 'without __set_name__' in str(e):
        type(instance).some_prop.__set_name__(type(instance), 'some_prop')
        value = instance.some_prop
    else:
        raise

Prevention

When it happens

Trigger: Calling the property on an instance after manually attaching the descriptor via setattr(SomeClass, 'name', prop) (setattr does not invoke __set_name__), or invoking __get__ directly before the class body finished; uncommon in normal Reflex usage but reachable through dynamic State class construction.

Common situations: Dynamically building State classes at runtime with type() or setattr and attaching Reflex cached_property/ComputedVar descriptors; monkeypatching state attributes in tests; mixing manual descriptor wiring with Reflex's State machinery.

Related errors


AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28). Data as JSON: /api/errors/55fa405baa23d18d. Report an issue: GitHub.