python/cpython · error · AttributeError
%r object attribute '__dict__' is read-only
Error message
%r object attribute '__dict__' is read-only
What it means
local.__setattr__ in the pure-Python threading.local implementation special-cases assignments to '__dict__' and raises AttributeError naming the class. The per-thread dict is managed internally via _localimpl/._patch, so replacing it from user code would break thread isolation.
Source
Thrown at Lib/_threading_local.py:105
raise TypeError("Initialization arguments are not supported")
self = object.__new__(cls)
impl = _localimpl()
impl.localargs = (args, kw)
impl.locallock = RLock()
object.__setattr__(self, '_local__impl', impl)
# We need to create the thread dict in anticipation of
# __init__ being called, to make sure we don't call it
# again ourselves.
impl.create_dict()
return self
def __getattribute__(self, name):
with _patch(self):
return object.__getattribute__(self, name)
def __setattr__(self, name, value):
if name == '__dict__':
raise AttributeError(
"%r object attribute '__dict__' is read-only"
% self.__class__.__name__)
with _patch(self):
return object.__setattr__(self, name, value)
def __delattr__(self, name):
if name == '__dict__':
raise AttributeError(
"%r object attribute '__dict__' is read-only"
% self.__class__.__name__)
with _patch(self):
return object.__delattr__(self, name)
from threading import current_thread, RLock
View on GitHub (pinned to bc6749cc3b)
Solutions
- Mutate the contents instead: for k in list(obj.__dict__): delattr(obj, k)
- Give the local subclass an explicit reset() method that deletes known attributes
- Use vars(obj) (read-only view of the per-thread dict) when you only need inspection
Example fix
# before
loc.__dict__ = {} # AttributeError: 'local' object attribute '__dict__' is read-only
# after
for k in list(vars(loc)):
delattr(loc, k) Defensive patterns
Strategy: try-catch
Validate before calling
def clear_local(loc):
for k in list(vars(loc)):
delattr(loc, k) Type guard
def supports_dict_rebind(obj) -> bool:
import threading
return not isinstance(obj, threading.local) Try / catch
try:
obj.__dict__ = new_dict
except AttributeError:
for k in list(vars(obj)):
delattr(obj, k)
for k, v in new_dict.items():
setattr(obj, k, v) Prevention
- Never rebind __dict__ on objects you do not own
- Reset thread-locals by deleting named attributes
- Prefer an explicit .reset() method on local subclasses
When it happens
Trigger: instance.__dict__ = {} or instance.__dict__['key'] = value via setattr-style assignment on a _threading_local.local (or subclass) instance.
Common situations: Generic plumbing code that 'clears' objects by rebinding obj.__dict__ = {} (works for normal objects, fails here); deepcopy/pickle helpers that manipulate __dict__ directly.
Related errors
- Initialization arguments are not supported
- detach_thread: failed detaching thread\n
- module 'collections.abc' has no attribute {attr!r}
- locale changed during initialization
- timezone changed during initialization
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/3fb6cdfeb676ebb4.
Report an issue: GitHub.