AttributeError: can't set attribute / property has no setter (tested)
AttributeError: can't set attribute and, since Python 3.11, property 'x' of 'C' object has no setter both mean you assigned to something read-only. We ran every common cause on Python 3.13.5, including two setter mistakes that look right.
1. The property has a getter and no setter
class Temp:
def __init__(self, c):
self._c = c
@property
def celsius(self):
return self._c
t = Temp(20)
try:
t.celsius = 25
except AttributeError as e:
print(type(e).__name__ + ":", e)
Output:
AttributeError: property 'celsius' of 'Temp' object has no setter
Measured on Python 3.13.5: the message is property 'celsius' of 'Temp' object has no setter. Python 3.11 changed this text; older versions said AttributeError: can't set attribute for the same mistake (not re-tested here, we only ran 3.13). Same bug, same fix.
2. It fails inside __init__ too
A common surprise: you never assign to the property “from outside”, but __init__ does self.celsius = c, which goes through the property:
class Temp:
def __init__(self, c):
self.celsius = c # goes through the property
@property
def celsius(self):
return self._c
try:
Temp(20)
except AttributeError as e:
print(type(e).__name__ + ":", e)
Output:
AttributeError: property 'celsius' of 'Temp' object has no setter
Either store into the backing name (self._c = c) or add a setter, as in section 4.
3. namedtuple and frozen dataclasses
from collections import namedtuple
from dataclasses import dataclass
Point = namedtuple("Point", "x y")
p = Point(1, 2)
try:
p.x = 10
except AttributeError as e:
print("namedtuple:", e)
print("fix:", p._replace(x=10))
@dataclass(frozen=True)
class Cfg:
port: int
c = Cfg(80)
try:
c.port = 8080
except AttributeError as e:
print(type(e).__name__ + ":", e)
Output:
namedtuple: can't set attribute
fix: Point(x=10, y=2)
FrozenInstanceError: cannot assign to field 'port'
Measured: on 3.13.5 a namedtuple still raises the old wording, can't set attribute, so that's the likely source if you see that exact text on a current Python. Use _replace() to get a modified copy. A @dataclass(frozen=True) raises FrozenInstanceError, which is a subclass of AttributeError (checked: issubclass(FrozenInstanceError, AttributeError) is True); use dataclasses.replace(c, port=8080).
4. The fix: add a setter with the same name
class Temp:
def __init__(self, c):
self.celsius = c
@property
def celsius(self):
return self._c
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("below absolute zero")
self._c = value
t = Temp(20)
t.celsius = 25
print(t.celsius)
Output:
25
5. Two setter mistakes that don't fix it
Forgetting the decorator: the second def celsius simply replaces the property with a plain function:
class Temp:
@property
def celsius(self):
return self._c
def celsius(self, value): # meant as a setter, missing @celsius.setter
self._c = value
t = Temp()
t._c = 1
print(type(Temp.__dict__["celsius"]).__name__)
try:
print(type(t.celsius).__name__, t.celsius == t._c)
except Exception as e:
print(type(e).__name__ + ":", e)
Output:
function
method False
Measured: no error at all, but Temp.celsius is now a plain function, so t.celsius is a bound method, not the value. Naming the setter function differently:
class Temp:
@property
def celsius(self):
return self._c
@celsius.setter
def set_celsius(self, value): # setter under a different name
self._c = value
t = Temp()
try:
t.celsius = 5
except AttributeError as e:
print(type(e).__name__ + ":", e)
t.set_celsius = 5
print(t.celsius)
Output:
AttributeError: property 'celsius' of 'Temp' object has no setter
5
Measured: @celsius.setter returns a new property bound to whatever name the function has. Under set_celsius, the original celsius is still read-only. The setter function must use the same name as the getter.
Frequently asked questions
What does AttributeError: can't set attribute mean?
You assigned to a read-only attribute: a property without a setter (Python 3.10 and earlier wording) or a namedtuple field (still this wording on 3.13.5, which we measured).
What does property object has no setter mean in Python?
Since Python 3.11 that's the message for assigning to a @property that has no @x.setter. Add a setter with the same function name, or assign to the backing attribute instead.
Why does my property fail in __init__?
self.name = value in __init__ goes through the property. We measured it raising the same no-setter error; set self._name directly or add a setter.
How do I change a field of a namedtuple?
You can't in place; use p._replace(x=10), which returns a new tuple. We measured it returning Point(x=10, y=2).
Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5 on Linux: a property without a setter (assigned outside and in __init__), namedtuple and frozen dataclass assignment, a correct setter, and two broken setter variants. Every block was run verbatim and its output pasted from that run. Pre-3.11 wording was not re-tested. PlainHeaders is our extension; everything else here is built-in Python.