Changing the error message when concatenating 'str' and 'NoneType'

(Running on Python 3.10.8)

>>> None + ""
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

The error message makes sense because the types, ‘NoneType’ and ‘str’, are in the order that matches the error in the code.

However, doing the reverse yields this:

>>> "" + None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "NoneType") to str

When taking a quick glance at the error (as most programmers do) on a densely packed terminal, here’s how I process it mentally:

Since “NoneType” is the only thing in quotes, my eyes look at it first. Since the phrase, “str” is to the right of it, I think the error means that I’m adding a “NoneType” + “str” and not the opposite. I think this is confusing. Reading the error message more closely clarifies things, but wouldn’t a more standardized TypeError error message structure be significantly easier to understand?

Here’s what I propose:

TypeError: unsupported operand type(s) for +: 'str' and 'NoneType'

instead of

TypeError: can only concatenate str (not "NoneType") to str

In situations where the types of the operands are ambiguous (i.e any variable), I feel that the unified message syntax would be really useful.

The error message for str, list, tuple and deque is more specific.

  1. It is concatenation. For other types ‘+’ can mean addition or other operation.
  2. It specifies not only what types are wrong, but what is expected. You can only add str to str, but many numeric types can be added to int or float.

Now, it is not completely true, because you can define a custom type which would do arbitrary things when added to str. There is even one such example in the stdlib:

>>> 'a' + unittest.mock.MagicMock()
<MagicMock name='mock.__radd__()' id='140321450854608'>

I do not know how to write in error message that in [] + x the second operator is expected to be a list, not tuple, not arbitrary iterable, and kept the technical correctness (it can also be MagicMock, but it is not what expected in 99% of cases).

1 Like

I agree with Serhiy that we should keep the more specific message.

Well there’s your problem right there. If your debugging technique is to only take a quick glance at things, then you’re going to have a bad time.

Most people read English from left to right, not from the middle out. I think this problem you are having is probably ideosyncratic to your unusual reading technique.

I don’t think it would be significantly easier to understand. Or even at all. How do you know that the error message order must always reflect that operand order? Is that promised somewhere in the documentation?

In this specific case, I have no objection to the wording you suggest. Nor do I prefer that wording. But unfortunately, as far as I understand it, there is no API for ensuring some consistent word order in error messages, and we almost certainly would not want to guarantee some specific word order. The error messages themselves are not part of the Python language API, so they are free to be changed at any point, or localised to another natural language. So that would mean any changes we make to the error message would have to be done one at a time, and could change again in the future.

Even if some error messages have been stable for decades, we probably don’t want to guarantee that stability.

See also: