Skip to content

Misleading "Not an instance or subtype" error when assigning to property of frozen, slotted dataclass #143969

Open

Description

@HalfWhitt

Bug report

Bug description:

When a dataclass is frozen, attempting to assign to a property (with a setter or without) fails as expected:

from dataclasses import dataclass

@dataclass(frozen=True)
class Example:
	a: int

	@property
	def prop(self):
		return None

example = Example(10)
example.prop = 0
  File "test_dataclass.py", line 12, in <module>
    example.prop = 0
    ^^^^^^^^^^^^
  File "<string>", line 15, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'prop'

And when the class is slotted, if the property has no setter, it also fails the way one would expect:

from dataclasses import dataclass

@dataclass(slots=True)
class Example:
	a: int

	@property
	def prop(self):
		return None

example = Example(10)
example.prop = 0
Traceback (most recent call last):
  File "test_dataclass.py", line 12, in <module>
    example.prop = 0
    ^^^^^^^^^^^^
AttributeError: property 'prop' of 'Example' object has no setter

(In this case, of course, adding a setter makes it work fine.)

What's unexpected (and confusing) is when the class is both frozen and slotted:

from dataclasses import dataclass

@dataclass(frozen=True, slots=True)
class Example:
	a: int

	@property
	def prop(self):
		return None

example = Example(10)
example.prop = 0
Traceback (most recent call last):
  File "test_dataclass.py", line 12, in <module>
    example.prop = 0
    ^^^^^^^^^^^^
  File "<string>", line 16, in __setattr__
TypeError: super(type, obj): obj (instance of Example) is not an instance or subtype of type (Example).

One would, of course, expect an instance of Example to in fact be an instance of Example, but maybe this is somehow a collision between the initial vs. dataclass-ified class definitions?

CPython versions tested on:

3.13

Operating systems tested on:

macOS

Linked PRs

Activity

  1. added 5 commits that reference this issue on Jan 17, 2026
  2. carljm commented on May 18, 2026

    @carljm
    Member

    This looks like #90562 -- maybe a case that was missed in the PR that closed that issue? cc @ericvsmith

  3. ericvsmith commented on May 19, 2026

    @ericvsmith
    Member

    @carljm : Yes, I think it's related to how #90562 modifies cells, but I can't noodle through exactly what the problem is. I'll try to give it some attention, but it's crazy complicated and as far as I can tell the best outcome is a less confusing error message.

  4. HalfWhitt commented on May 19, 2026

    @HalfWhitt
    Author

    Functioning correctly / intuitively would be ideal, but yeah, a clear error message would definitely be an improvement!

  5. self-assigned this
    on May 19, 2026
  6. sobolevn commented on May 19, 2026

    @sobolevn
    Member

    3.15 and main versions already produce:

    » ./python.exe ex.py
    Traceback (most recent call last):
      File "/Users/sobolev/Desktop/cpython/ex.py", line 12, in <module>
        example.prop = 0
        ^^^^^^^^^^^^
      File "<string>", line 15, in __setattr__
    dataclasses.FrozenInstanceError: cannot assign to field 'prop'

    And changing error message for 3.14 does not feel right at this moment :(

  7. sobolevn commented on May 19, 2026

    @sobolevn
    Member

    However, it is still not ideal: it says that prop is a field, while it is a property, not a field, and is not listed in dataclasses.fields(Example).

    from dataclasses import dataclass
    
    @dataclass(frozen=True)
    class Example:
        a: int
    
        @property
        def prop(self):
            return None
    
        @prop.setter
        def prop(self, val):
            print(val)
    
    
    example = Example(10)
    example.prop = 0

    produces:

    » ./python.exe ex.py
    Traceback (most recent call last):
      File "/Users/sobolev/Desktop/cpython/ex.py", line 17, in <module>
        example.prop = 0
        ^^^^^^^^^^^^
      File "<string>", line 15, in __setattr__
    dataclasses.FrozenInstanceError: cannot assign to field 'prop'
    
  8. chet-manley commented on Aug 15, 2026

    @chet-manley

    Edit:
    Turns out I was unexpectedly running patch version 3.14.4, which was a version before the below patch hit release. Seems to work fine on 3.14.6 & 3.14.7 (the two versions I re-tested). I refactored my dynamic patch and have 3.10.x to 3.14.x working fine now. You can probably disregard my original comment below.


    I can verify this is also an issue in CPython 3.14.x. Appears to me that #105936 fixed most of the issue, but left out property and property sub-classed decorated methods. I am currently working around it with a custom base class that intercepts __setattr__ and __delattr__, sending the calls back through the properties' __set__ and __delete__ methods.

    FWIW: the issue is that slots=True creates a brand new class and the __setattr__ and __delattr__ closures created by frozen=True still point to the original class:

    >>> func = Runtime.__setattr__
    >>> if func.__closure__:
    ...     cell_contents = func.__closure__[1].cell_contents
    ...     print(f"Closure Cell target: {cell_contents}")
    ...     print(f"Actual Runtime class: {Runtime}")
    ...     print(f"MisMatch: {cell_contents is not Runtime}", id(cell_contents), id(Runtime))
    Closure Cell target: <class 'adminx.core.runtime.Runtime'>
    Actual Runtime class: <class 'adminx.core.runtime.Runtime'>
    MisMatch: True 89678934872464 89678934899344
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytopic-dataclassestype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions