reflex-dev/reflex · error · TypeError
Cannot assign the same cached_property to two different name
Error message
Cannot assign the same cached_property to two different names ({self._attrname!r} and {name!r}). What it means
This is CPython's cached_property guard reimplemented in Reflex: a single cached_property descriptor instance was assigned to two different attributes of the same class. Python's cached_property stores its attribute name in _attrname when __set_name__ runs, and refuses to be reused under a second name. Reflex's copy preserves that invariants check.
Source
Thrown at packages/reflex-base/src/reflex_base/vars/base.py:2051
try:
unique_id = object.__getattribute__(this, cached_field_name)
except AttributeError:
if original_del is not None:
original_del(this)
return
GLOBAL_CACHE.pop(unique_id, None)
if original_del is not None:
original_del(this)
owner.__del__ = delete_property
elif name != self._attrname:
msg = (
"Cannot assign the same cached_property to two different names "
f"({self._attrname!r} and {name!r})."
)
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._attrnameView on GitHub (pinned to 45b8ed5ab7)
Solutions
- Create a fresh property for each attribute (call the decorator/factory once per name, or copy.copy the descriptor before reassigning)
- If aliasing is intentional, use functools.cached_property semantics correctly: re-run the decorator for the second name instead of assigning the same object
- Find the duplicate assignment with grep for the attribute/property name in class bodies and metaprogramming code
Example fix
# before
make_prop = _cached_property(some_fget)
class MyState(rx.State):
a = make_prop
b = make_prop # TypeError
# after
class MyState(rx.State):
a = _cached_property(some_fget)
b = _cached_property(other_fget) # or the same callable, new descriptor
# or alias the result, not the descriptor:
# b = property(lambda self: self.a) Defensive patterns
Strategy: validation
Validate before calling
def validate_cached_props(cls) -> None:
seen = {}
for name in vars(cls):
obj = vars(cls)[name]
attrname = getattr(obj, '_attrname', None)
if attrname is not None and obj is not getattr(cls, attrname, obj):
pass
if id(obj) in seen:
raise TypeError(f'{type(obj).__name__} assigned to both {seen[id(obj)]!r} and {name!r}')
seen[id(obj)] = name Type guard
def is_fresh_descriptor(obj, assigned_names: set[str]) -> bool:
# a cached_property may only be assigned to one name per class
return id(obj) not in assigned_names Prevention
- Never assign one decorator result to multiple attributes; run the decorator once per name
- In metaprogramming, use copy.copy(descriptor) before reassigning to a new name
- Lint dynamically generated State classes for duplicate descriptor object ids
When it happens
Trigger: Assigning the same cached_property object to two class attributes, e.g. cp = _cached_property(f); class S: a = cp; b = cp, or dynamically attaching one ComputedVar/cached property object to multiple attribute names in a State class (e.g. via setattr in a loop or metaprogramming).
Common situations: Metaprogramming over State classes that copies ComputedVar/cached_property descriptors between attributes; applying the same decorator result to multiple methods; refactoring state mixins where a property object gets aliased instead of re-created.
Related errors
- Cannot use cached_property on a class without __set_name__.
- The component `{comp_name}` only allows the components: {val
- Var-returning `@rx.memo` `{func_name}` cannot depend on embe
- Var-returning `@rx.memo` `{func_name}` cannot import `{lib}`
- `rx.Var[rx.Component]` parameters in `{fn_name}` must be nam
AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28).
Data as JSON: /api/errors/b22320a98baf1041.
Report an issue: GitHub.