{"record":{"id":"3fb6cdfeb676ebb4","repo":"python/cpython","slug":"r-object-attribute-dict-is-read-only","errorCode":null,"errorMessage":"%r object attribute '__dict__' is read-only","messagePattern":"%r object attribute '__dict__' is read-only","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"Lib/_threading_local.py","lineNumber":105,"sourceCode":"            raise TypeError(\"Initialization arguments are not supported\")\n        self = object.__new__(cls)\n        impl = _localimpl()\n        impl.localargs = (args, kw)\n        impl.locallock = RLock()\n        object.__setattr__(self, '_local__impl', impl)\n        # We need to create the thread dict in anticipation of\n        # __init__ being called, to make sure we don't call it\n        # again ourselves.\n        impl.create_dict()\n        return self\n\n    def __getattribute__(self, name):\n        with _patch(self):\n            return object.__getattribute__(self, name)\n\n    def __setattr__(self, name, value):\n        if name == '__dict__':\n            raise AttributeError(\n                \"%r object attribute '__dict__' is read-only\"\n                % self.__class__.__name__)\n        with _patch(self):\n            return object.__setattr__(self, name, value)\n\n    def __delattr__(self, name):\n        if name == '__dict__':\n            raise AttributeError(\n                \"%r object attribute '__dict__' is read-only\"\n                % self.__class__.__name__)\n        with _patch(self):\n            return object.__delattr__(self, name)\n\n\nfrom threading import current_thread, RLock\n","sourceCodeStart":87,"sourceCodeEnd":121,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_threading_local.py#L87-L121","documentation":"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.","triggerScenarios":"instance.__dict__ = {} or instance.__dict__['key'] = value via setattr-style assignment on a _threading_local.local (or subclass) instance.","commonSituations":"Generic plumbing code that 'clears' objects by rebinding obj.__dict__ = {} (works for normal objects, fails here); deepcopy/pickle helpers that manipulate __dict__ directly.","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"],"exampleFix":"# before\nloc.__dict__ = {}  # AttributeError: 'local' object attribute '__dict__' is read-only\n\n# after\nfor k in list(vars(loc)):\n    delattr(loc, k)","handlingStrategy":"try-catch","validationCode":"def clear_local(loc):\n    for k in list(vars(loc)):\n        delattr(loc, k)","typeGuard":"def supports_dict_rebind(obj) -> bool:\n    import threading\n    return not isinstance(obj, threading.local)","tryCatchPattern":"try:\n    obj.__dict__ = new_dict\nexcept AttributeError:\n    for k in list(vars(obj)):\n        delattr(obj, k)\n    for k, v in new_dict.items():\n        setattr(obj, k, v)","preventionTips":["Never rebind __dict__ on objects you do not own","Reset thread-locals by deleting named attributes","Prefer an explicit .reset() method on local subclasses"],"tags":["threading","thread-local","attributeerror","cpython"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}