Skip to content

Nested AttributeError improved messages don't work with properties #146171

Description

@rodrigogiraoserrao

The Python 3.15 improved error message for nested attribute access doesn't seem to work on properties.

Rationale

Take the example from the What's new in Python 3.15 docs:

from dataclasses import dataclass

@dataclass
class Circle:
   radius: float

   @property
   def area(self) -> float:
      return pi * self.radius**2

class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner

circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)

Running it with the CPython main branch or Python 3.15.0a1 through Python 3.15.0a7 (with uv) produces the following error:

Traceback (most recent call last):
  File "/Users/rodrigogs/Documents/cpython/../tmp/circle.py", line 17, in <module>
    print(container.area)
          ^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'area'

If you remove @property or if you try accessing container.radius instead, you get the respective improved messages:

# After removing `@property` from `area`:
Traceback (most recent call last):
  File "/Users/rodrigogs/Documents/cpython/../tmp/circle_no_prop.py", line 16, in <module>
    print(container.area)
          ^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'area'. Did you mean: 'inner.area'?

# ---

# Accessing `radius` instead of the property `area`:
Traceback (most recent call last):
  File "/Users/rodrigogs/Documents/cpython/../tmp/circle_radius.py", line 17, in <module>
    print(container.radius)
          ^^^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'radius'. Did you mean: 'inner.radius'?

Helper scripts for easier testing

circle.py — original example that doesn't work
from dataclasses import dataclass

@dataclass
class Circle:
   radius: float

   @property
   def area(self) -> float:
      return pi * self.radius**2

class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner

circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)
circle_radius.py — accessing radius works
from dataclasses import dataclass

@dataclass
class Circle:
   radius: float

   @property
   def area(self) -> float:
      return pi * self.radius**2

class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner

circle = Circle(radius=4.0)
container = Container(circle)
print(container.radius)
circle_no_prop.py — removing the property works
from dataclasses import dataclass

@dataclass
class Circle:
   radius: float

   # @property
   def area(self) -> float:
      return pi * self.radius**2

class Container:
   def __init__(self, inner: Circle) -> None:
      self.inner = inner

circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)

CPython versions tested on:

3.15, CPython main branch

Operating systems tested on:

macOS

Linked PRs

Activity

  1. hugovk commented on Mar 19, 2026

    @hugovk
    Member
  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Mar 19, 2026
  3. okiemute04 commented on Mar 19, 2026

    @okiemute04
    Contributor

    @rodrigogiraoserrao just analyzed the issue. The problem is that the nested attribute suggestion system doesn't understand properties. My proposed solution is to enhance the error suggestion algorithm to recognize property descriptors and examine their getter functions when generating suggestions. This would maintain the existing behavior for regular attributes while adding property support. What do you think? Any suggestions or options that will be a good fit for this issue?

  4. added a commit that references this issue on Mar 20, 2026
  5. pablogsal commented on Mar 20, 2026

    @pablogsal
    Member

    @rodrigogiraoserrao just analyzed the issue. The problem is that the nested attribute suggestion system doesn't understand properties. My proposed solution is to enhance the error suggestion algorithm to recognize property descriptors and examine their getter functions when generating suggestions. This would maintain the existing behavior for regular attributes while adding property support. What do you think? Any suggestions or options that will be a good fit for this issue?

    Sorry, I didn't read this message earlier.

    I ended up taking a slightly different approach from examining the getter function directly. The fix uses static attribute lookup for nested suggestions, so property-backed attributes can be suggested without executing the property getter. That keeps the existing behavior for regular attributes and avoids triggering arbitrary code while formatting the error.

    If you want to help, reviewing the change and testing a few edge cases would be useful!

  6. pablogsal commented on Mar 20, 2026

    @pablogsal
    Member

    Thanks @rodrigogiraoserrao for the find! ❤️

  7. okiemute04 commented on Mar 20, 2026

    @okiemute04
    Contributor

    @pablogsal I tested this PR locally with the property example from #146171 and confirmed:

    ✅ The property getter is not executed (no side effects)

    ✅ The tests test_getattr_nested_with_property passed and are working as they should

    ✅ The error message correctly suggests inner.computed for the property-backed attribute

    Great work !!!!!!!!!!

  8. pablogsal commented on Mar 20, 2026

    @pablogsal
    Member

    Thanks a lot @okiemute04 🖤

  9. added a commit that references this issue on Mar 20, 2026
  10. rodrigogiraoserrao commented on Mar 20, 2026

    @rodrigogiraoserrao
    ContributorAuthor

    Well, that was quick. 👀 Thanks to both!

  11. added a commit that references this issue on Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions