GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Inconsistent error messages when returning the wrong type for the type-conversion magic methods · Issue #130821 · python/cpython

Inconsistent error messages when returning the wrong type for the type-conversion magic methods #130821

New issue
Copy link
New issue
Copy link
Open
Open
Inconsistent error messages when returning the wrong type for the type-conversion magic methods#130821
Copy link
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement

Description

@mxgordon
mxgordon
opened on Mar 4, 2025
Issue body actions

Bug report

Bug description:

I noticed the error messages between magic methods like __int__ and __float__ were inconsistent. This seems like slightly undesirable behavior to me. I used the following code to generate many of them.

class Foo:
    def __int__(self):
        return None
    
    def __float__(self):
        return None
    
    def __bytes__(self):
        return None
    
    def __complex__(self):
        return None
    
    def __bool__(self):
        return None
    
    def __str__(self):
        return None

try:
    int(Foo())
except Exception as e:
    print(e)

try:
    float(Foo())
except Exception as e:
    print(e)

try:
    bytes(Foo())
except Exception as e:
    print(e)

try:
    complex(Foo())
except Exception as e:
    print(e)

try:
    bool(Foo())
except Exception as e:
    print(e)

try:
    str(Foo())
except Exception as e:
    print(e)

And the output is as follows:

__int__ returned non-int (type NoneType)
Foo.__float__ returned non-float (type NoneType)
__bytes__ returned non-bytes (type NoneType)
__complex__ returned non-complex (type NoneType)
__bool__ should return bool, returned NoneType
__str__ returned non-string (type NoneType)

The first issue I've made, but seems like a reasonable bug. I'm not sure if there are other "type-conversion" magic methods out there that aren't consistent.

CPython versions tested on:

3.13, 3.12

Operating systems tested on:

Windows

Linked PRs

  • gh-130821: Add type information to wrong type error messages #130835
  • gh-130821: Make error messages consistent in Modules/ #144737
  • gh-130821: Add type information to error messages for remaining magic methods #144827
  • gh-130821: Add type info to error messages for __len__ and __sizeof__ #151894
  • gh-130821: Improve error messages for magic methods returning wrong type #154606
  • gh-130821: Add type info to error message in Modules/_abc.c #156080
  • gh-130821: Add type info to error message in Modules/_abc.c #156120

Activity

Next
  1. mxgordon
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Mar 4, 2025
  2. skirpichev commented on Mar 4, 2025

    @skirpichev
    skirpichev
    on Mar 4, 2025
    Member
    More actions

    The difference is

    cpython/Objects/abstract.c

    Lines 1529 to 1534 in d780f0a

    if (!PyLong_Check(result)) {
    PyErr_Format(PyExc_TypeError,
    "__int__ returned non-int (type %.200s)",
    Py_TYPE(result)->tp_name);
    Py_DECREF(result);
    return NULL;

    vs

    cpython/Objects/abstract.c

    Lines 1607 to 1612 in d780f0a

    if (!PyFloat_Check(res)) {
    PyErr_Format(PyExc_TypeError,
    "%.50s.__float__ returned non-float (type %.50s)",
    Py_TYPE(o)->tp_name, Py_TYPE(res)->tp_name);
    Py_DECREF(res);
    return NULL;

    CC @serhiy-storchaka as author of 16931c3.

    I don't think that inconsistency is a real bug. But that does make sense for me as a feature request: i.e. include type information to the exception message.

    Reacted by Serhiy Storchaka
  3. skirpichev
    added
    type-featureA feature request or enhancementA feature request or enhancement
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    and removed
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Mar 4, 2025
  4. serhiy-storchaka
    added
    3.14bugs and security fixesbugs and security fixes
    on Mar 4, 2025
  5. ZeroIntensity
    added
    easy
    on Mar 4, 2025
  6. ZeroIntensity commented on Mar 4, 2025

    @ZeroIntensity
    ZeroIntensity
    on Mar 4, 2025
    Member
    More actions

    I've marked this as easy for anyone that wants to dive into the C code for the first time.

  7. donbarbos commented on Mar 4, 2025

    @donbarbos
    donbarbos
    on Mar 4, 2025
    Contributor
    More actions

    if no one minds I'm going to send a PR with a unified message using as a reference message: Foo.__float__ returned non-float (type NoneType)

  8. donbarbos commented on Mar 4, 2025

    @donbarbos
    donbarbos
    on Mar 4, 2025
    Contributor
    More actions

    but after "grep" sources i found more cases with "returned non-" template, excluding tests and docs:

    grep output
    
    ./Objects/abstract.c:                     "__index__ returned non-int (type %.200s)",
    ./Objects/abstract.c:            "__index__ returned non-int (type %.200s).  "
    ./Objects/abstract.c:                         "__int__ returned non-int (type %.200s)",
    ./Objects/abstract.c:                "__int__ returned non-int (type %.200s).  "
    ./Objects/abstract.c:                         "%.50s.__float__ returned non-float (type %.50s)",
    ./Objects/abstract.c:                "%.50s.__float__ returned non-float (type %.50s).  "
    ./Objects/abstract.c:                         "iter() returned non-iterator "
    ./Objects/bytesobject.c:                         "__bytes__ returned non-bytes (type %.200s)",
    ./Objects/bytesobject.c:                        "__bytes__ returned non-bytes (type %.200s)",
    ./Objects/complexobject.c:                "__complex__ returned non-complex (type %.200s)",
    ./Objects/complexobject.c:                "__complex__ returned non-complex (type %.200s).  "
    ./Objects/funcobject.c:            PyErr_Format(PyExc_TypeError, "__annotate__ returned non-dict of type '%.100s'",
    ./Objects/moduleobject.c:                PyErr_Format(PyExc_TypeError, "__annotate__ returned non-dict of type '%.100s'",
    ./Objects/object.c:                      "__repr__ returned non-string (type %.200s)",
    ./Objects/object.c:                      "__str__ returned non-string (type %.200s)",
    ./Objects/object.c:                         "__bytes__ returned non-bytes (type %.200s)",
    ./Objects/fileobject.c:                   "object.readline() returned non-string");
    ./Objects/floatobject.c:                         "%.50s.__float__ returned non-float (type %.50s)",
    ./Objects/floatobject.c:                "%.50s.__float__ returned non-float (type %.50s).  "
    ./Objects/genobject.c:                             "__await__() returned non-iterator "
    ./Objects/typeobject.c:                PyErr_Format(PyExc_TypeError, "__annotate__ returned non-dict of type '%.100s'",
    ./Objects/typeobject.c:                     "__buffer__ returned non-memoryview object");
    ./Lib/subprocess.py:            return "Command '%s' returned non-zero exit status %d." % (
    ./Modules/_datetimemodule.c:                         "divmod() returned non-tuple (type %.200s)",
    ./Modules/_abc.c:                "items() returned non-iterable");
    ./Modules/_pickle.c:                         "read() returned non-bytes object (%R)",
    

    should we add type information to other methods and to methods from modules in stdlib?

  9. picnixz
    removed
    3.14bugs and security fixesbugs and security fixes
    on Mar 4, 2025
  10. serhiy-storchaka commented on Mar 4, 2025

    @serhiy-storchaka
    serhiy-storchaka
    on Mar 4, 2025
    Member
    More actions

    Looks like a nice idea to me.

    You can use %T and %N to format type names in C.

  11. donbarbos commented on Mar 6, 2025

    @donbarbos
    donbarbos
    on Mar 6, 2025
    Contributor
    More actions

    but after "grep" sources i found more cases with "returned non-" template, excluding tests and docs:
    grep output

    should we add type information to other methods and to methods from modules in stdlib?

    here are more examples of error messages:

    __len__() should return >= 0
    __hash__ method should return an integer
    __init__() should return None, not '%.200s'
    __sizeof__() should return >= 0
    __getnewargs_ex__ should return a tuple, not '%.200s'
    __getnewargs_ex__ should return a tuple of length 2, not %zd
    __length_hint__() should return >= 0
    __length_hint__ must be an integer, not %.100s
    read() should return bytes
    readall() should return bytes
    decoder should return a string result, not '%.200s'
    encoder should return a bytes object, not '%.200s'
    iterator should return strings, not %.200s (the file should be opened in text mode)
    

    I suggest using the following template for all of them: {TYPE}.__method__ should return ..., not ... (or must return)
    unfortunately we don't have a PEP about error messages, but we had a similar PR #127345 and I found discuss

  12. serhiy-storchaka commented on Mar 6, 2025

    @serhiy-storchaka
    serhiy-storchaka
    on Mar 6, 2025
    Member
    More actions

    I like it. But since it's such a wide change, we need approval from more core developers. Could you open a discussion at https://discuss.python.org/?

    I think also that there should be parentheses after the method name. This would help to distinguish them from attributes.

    Reacted by Semyon Moroz
  13. donbarbos commented on Mar 6, 2025

    @donbarbos
    donbarbos
    on Mar 6, 2025
    Contributor
    More actions

    Could you open a discussion at https://discuss.python.org/?

    yes, i can. but should i propose in this discussion to create PEP or just propose to change error messages of the methods i have cited?

    EDIT: I don't mind if you open it. Maybe you know better what to use as arguments :)

  14. 9 remaining items

  15. Agent-Hellboy
    added a commit that references this issue on Aug 19, 2025

    pythongh-130821: Add type information to error messages for invalid r…

    b28f775
  16. Cityfishman
    added a commit that references this issue on Feb 12, 2026

    pythongh-130821: Make error messages consistent in Modules/

    a832eec
  17. dioput12 commented on Apr 23, 2026

    @dioput12
    dioput12
    on Apr 23, 2026
    More actions

    Hello All, I just tried this minimal_repro.py and here's the result on Termux with 3.13.13 version:

    # Run: python3 -c "..."
    
    # __int__ returns the wrong type
    class A:
        def __int__(self): return "not an int"
    
    class B:
        def __float__(self): return 42  # returns an int, not a float
    
    class C:
        def __bool__(self): return 1.0  # returns a float, not a bool
    
    class D:
        def __index__(self): return 3.14
    
    try: int(A())
    except TypeError as e: print(f"__int__:   {e}")
    
    try: float(B())
    except TypeError as e: print(f"__float__: {e}")
    
    try: bool(C())
    except TypeError as e: print(f"__bool__: {e}")
    
    try: D()[0:1]
    except TypeError as e: print(f"__index__: {e}")
    ~ $ python3 minimal_repro.py
    __int__:   __int__ returned non-int (type str)
    __float__: B.__float__ returned non-float (type int)
    __bool__: __bool__ should return bool, returned float
    __index__: 'D' object is not subscriptable
    ~ $
  18. tangyuan0821
    added 3 commits that reference this issue on Jun 22, 2026

    pythongh-130821: Add type info to error messages for __len__ and __si…

    ca04d89

    pythongh-130821: Add news entry for __len__ and __sizeof__ error mess…

    9c2be49

    pythongh-130821: Add news entry for __len__ and __sizeof__ error mess…

    abf13a8
  19. prabhleen-kaurr
    added a commit that references this issue on Jul 24, 2026

    pythongh-130821: Add NEWS entry

    496f95c
  20. JMak-Security commented on Aug 20, 2026

    @JMak-Security
    JMak-Security
    on Aug 20, 2026
    Contributor
    More actions

    I found that Modules/_abc.c is still using the old "items() returned non-iterable" error format. I am currently working on a patch to update it to the new consistent format with type information!

  21. JMak-Security
    added 3 commits that reference this issue on Aug 20, 2026

    pythongh-130821: Add type info to error message in Modules/_abc.c

    32deaa9

    pythongh-130821: Refactor _abc.c error message to use standard %T

    9dc6c5d

    pythongh-130821: Fix syntax typo in Modules/_abc.c error message

    4fc5bba
  22. picnixz
    removed
    easy
    on Aug 20, 2026
  23. JMak-Security commented on Aug 20, 2026

    @JMak-Security
    JMak-Security
    on Aug 20, 2026
    Contributor
    More actions

    Since PR #144737 has gone stale, I would love to take over this issue. I can port over my fixes for _abc.c, tackle the other listed modules, and address the reviewer's feedback regarding whether we should switch to TypeError or keep ValueError in _pickle.c.

  24. JMak-Security
    added a commit that references this issue on Aug 20, 2026

    pythongh-130821: Add type info to error message in Modules/_abc.c

    17ba47e
  25. JMak-Security commented on Aug 20, 2026

    @JMak-Security
    JMak-Security
    on Aug 20, 2026
    Contributor
    More actions

    Opened #156120 for the Modules/_abc.c piece — narrower in scope than #144737 (just this one file), and fixes a NULL-dereference risk found in that PR's version of the same hunk (passing NULL as the message to PySequence_Fast(), which can reach PyErr_SetString(exc, NULL) on a genuine TypeError). Left a note on #144737 as well. Not touching the other Modules/ files yet since the _pickle.c ValueError/TypeError question there is still open and this issue is still flagged as needing broader consensus before a repo-wide sweep.

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

    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402520 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.