The line that raised is where two shapes met. It is almost never where the wrong one was made.
Finding the axis is the part you can do on paper. In a running program there is a second half, and it is the half that costs the afternoon: the shapes are a symptom, and the line in the traceback is where the symptom showed, not where the disease is. Here is one as it actually arrives:
Traceback (most recent call last):
File "/work/train.py", line 62, in <module>
scaled = features * weights
~~~~~~~~~^~~~~~~~~
ValueError: operands could not be broadcast together with shapes (60000,784) (785,)
Three parts of that pull their weight, and it is worth knowing which:
- The frame -- file and line -- says where. If the traceback runs through a library, read it from the bottom upwards and stop at the last file you wrote. That frame is yours; the ones below it are the library doing what you asked it to.
- The caret line says which operation. On a line with three of them, it is the only thing that tells you which one blew up, and you get it without splitting the expression across four statements to find out.
- The shapes say what met. They are printed as you passed them, unpadded, in operand order.
Then comes the step people skip. One of those two shapes is the one you meant and the other is not, and the multiply is innocent of both. Above, 784 columns against 785 weights is an off-by-one in how the weights were built -- perhaps a bias column that was concatenated twice, perhaps one that was never dropped. Editing the line that raised can only ever hide it.
So: pick the shape you did not expect, find where that array was last assigned, and fix it there. A reduction that dropped an axis, a model whose predictions come back as a column, a df[["y"]] where you wanted df["y"] -- the origin is usually a long way above the crash.
Two related messages are worth recognizing on sight, because they mean the destination got involved rather than the inputs:
ValueError: non-broadcastable output operand with shape (3,1)
doesn't match the broadcast shape (3,3)
ValueError: could not broadcast input array from shape (3,) into shape (4,)
The first is an in-place operation, a += b. Broadcasting is allowed to stretch the operands it reads; it is not allowed to grow the array it writes into, so an a that would have to become bigger raises instead. The second is an assignment into a slice, a[...] = b, where the right-hand side has to fit the destination it is being poured into. Both are about where the answer is going, which is why neither reads like the message you were expecting.