TypeError: 'str' / 'tuple' object does not support item assignment (tested fix)
TypeError: 'str' object does not support item assignment (or 'tuple') means you tried x[i] = value on an immutable type. We reproduced it on six types in Python 3.13 and tested the fixes, including a case where the change happens even though the error is raised.
1. Which types are immutable
obj[i] = value only works on mutable containers such as list, dict and bytearray. Strings, tuples and a few other built-ins can't be changed in place, so item assignment raises TypeError with the type name in the message. We tried six types:
cases = {"str": "hello", "tuple": (1, 2, 3), "bytes": b"abc", "range": range(3), "frozenset": frozenset({1}), "dict_keys": {}.keys()}
for name, obj in cases.items():
try:
obj[0] = 9
print(f"{name:10} OK")
except TypeError as e:
print(f"{name:10} TypeError: {e}")
Output:
str TypeError: 'str' object does not support item assignment
tuple TypeError: 'tuple' object does not support item assignment
bytes TypeError: 'bytes' object does not support item assignment
range TypeError: 'range' object does not support item assignment
frozenset TypeError: 'frozenset' object does not support item assignment
dict_keys TypeError: 'dict_keys' object does not support item assignment
2. The fix: build a new value
You can't change a string or tuple, but you can build a new one and rebind the name. Slice and concatenate, or convert to a list, edit it, and convert back:
s = "hello"
s2 = "j" + s[1:] # slice and rebuild
chars = list(s); chars[0] = "j" # or edit a list, then join
print(s2, "".join(chars), s.replace("h", "j", 1))
t = (1, 2, 3)
t2 = t[:1] + (9,) + t[2:] # build a new tuple
lst = list(t); lst[1] = 9
print(t2, tuple(lst))
Output:
jello jello jello
(1, 9, 3) (1, 9, 3)
For bytes, use a bytearray. It is mutable, so b = bytearray(b"abc"); b[0] = 106 works and gives bytearray(b'jbc').
3. The common trap: a string inside a dict or list
The container is mutable, but the value you indexed into isn't. Here the second [0] targets the str, not the dict:
d = {"name": "ann"}
d["name"][0] = "A" # the str inside the dict, not the dict
Output:
Traceback (most recent call last):
File "/tmp/ia/b3.py", line 2, in <module>
d["name"][0] = "A" # the str inside the dict, not the dict
~~~~~~~~~^^^
TypeError: 'str' object does not support item assignment
Assign a new string to the key instead. A related surprise goes the other way: a list inside a tuple can be mutated, and t[0] += [4] raises the TypeError after it has already extended the list:
d = {"name": "ann"}
d["name"] = "A" + d["name"][1:] # assign a new string to the dict key
print(d)
t = ([1, 2], "x")
t[0].append(3) # mutating a list INSIDE a tuple works
print(t)
try:
t[0] += [4] # but += on a tuple item raises... after mutating
except TypeError as e:
print("TypeError:", e)
print(t)
Output:
{'name': 'Ann'}
([1, 2, 3], 'x')
TypeError: 'tuple' object does not support item assignment
([1, 2, 3, 4], 'x')
That happens because += on a list mutates it in place first, and only then tries to store the result back into the tuple slot. Use t[0].extend(...) or t[0].append(...) to avoid the half-applied error.
4. namedtuple: a different error
Setting a namedtuple field by attribute gives AttributeError, not TypeError. Use _replace to get a modified copy:
from collections import namedtuple
P = namedtuple("P", "x y")
p = P(1, 2)
try:
p.x = 5
except AttributeError as e:
print("AttributeError:", e)
print(p._replace(x=5))
Output:
AttributeError: can't set attribute
P(x=5, y=2)
If you need fields you can edit, use a dataclass or a dict instead. For the related read-side error, see object is not subscriptable.
Frequently asked questions
How do I fix 'str' object does not support item assignment?
Strings are immutable. Build a new one: s = s[:i] + 'x' + s[i+1:], or edit list(s) and ''.join() it back.
How do I change a value in a tuple?
Build a new tuple (t[:i] + (v,) + t[i+1:]) or convert with list(t), edit, and convert back with tuple().
Why did my list inside a tuple change even though += raised TypeError?
list += mutates the list in place first, then the tuple refuses the store. Use .extend() or .append() on the inner list instead.
Written with AI assistance. Measured on 2026-10-22 on Debian with Python 3.13.5: item assignment on str, tuple, bytes, range, frozenset and dict_keys, the rebuild fixes, a str inside a dict, += on a list inside a tuple, and namedtuple fields. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.