Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

Python, From Zero, For AI

From your first line of code to your first API call.

Lesson 30 of 899 min

Reading an error message properly

Errors are the most useful output Python produces

Nobody writes correct code first time. Not beginners, not people with twenty years of practice. The difference between the two is almost entirely how fast they read the error and know where to look. This lesson is that skill, and it is worth more than any syntax you will learn this month.

There are two kinds of failure, and telling them apart saves you time.

Kind one: it never started

python
prices = [120, 340, 90
print("done")
  File "budget.py", line 1
    prices = [120, 340, 90
             ^
SyntaxError: '[' was never closed

A SyntaxError means Python could not read the file, so nothing ran at all. No output from earlier lines, because there were no earlier lines as far as Python is concerned.

One honest warning: for unclosed brackets and quotes, the reported line is often not where you would say the mistake is. Python keeps reading, hoping the bracket closes, and complains where it gives up. Newer Python versions point back at the opening bracket, as above. Older ones say invalid syntax on the following line. So when a syntax error makes no sense, look at the line above it, and count your brackets and quotes.

Kind two: it started and then hit something impossible

This is a traceback, and it has a shape worth learning. Here is a real program:

python
# budget.py
bills = {"food": [200, 150], "transport": [60]}

def total_for(name):
    return sum(bills[name])

print(total_for("food"))
print(total_for("rent"))

Running it:

350
Traceback (most recent call last):
  File "budget.py", line 8, in <module>
    print(total_for("rent"))
          ~~~~~~~~~^^^^^^^^
  File "budget.py", line 5, in total_for
    return sum(bills[name])
               ~~~~~^^^^^^
KeyError: 'rent'

Read the last line first. KeyError: 'rent' is what went wrong: something asked a dict for a key called rent and there is no such key. The error type tells you the category; the bit after the colon tells you the specific value involved.

Then read upwards. The blocks above are the chain of calls that got you there, oldest at the top, most recent at the bottom, which is what "most recent call last" means in the header. The bottom block, line 5, is where the failure actually happened. The block above it, line 8, is the line that called it.

So the broken line is 5, and the reason it broke is on line 8: someone asked for "rent", which is not in bills. Fixing line 5 would be fixing the wrong thing. The squiggles and carets under the code point at the exact expression that failed, which is a real help on a long line.

Reading a traceback in the order that finds the bugLast line firstThe error typeand message:what went wrongLowest blocknaming yourfileThat is where itbrokeThen readupwardsOldest call atthe top, mostrecent at thebottomPrint thevaluesThe line usuallylooks right; thevalue handed toit was notFix the callerThe line thatraised is oftencorrectReading top to bottom is the habit to break: the top of a traceback is the oldest call, which isusually main() and tells you nothing. Everything printed before the traceback did happen, so theprogram worked until it did not.
Reading a traceback in the order that findsthe bugLast line firstThe error type and message: what went wrongLowest block naming your fileThat is where it brokeThen read upwardsOldest call at the top, most recent at thebottomPrint the valuesThe line usually looks right; the value handedto it was notFix the callerThe line that raised is often correctReading top to bottom is the habit to break: the topof a traceback is the oldest call, which is usuallymain() and tells you nothing. Everything printedbefore the traceback did happen, so the programworked until it did not.

Also notice: 350 printed first. The program worked until it did not. Whatever printed before the traceback did happen.

The errors you will actually meet

  • NameError: name 'totl' is not defined — a typo, or you used a name before creating it, or it was created inside a function.
  • TypeError: can only concatenate str (not "int") to str — a number where text was expected, or the reverse. Very often an input() you forgot to convert.
  • TypeError: ... 'NoneType' ... — you used the result of a function that printed instead of returning.
  • IndexError: list index out of range — you asked for position 3 of a 3-item list. Valid positions are 0, 1, 2.
  • KeyError: 'rent' — the dict has no such key. Check spelling and capitals.
  • AttributeError: 'list' object has no attribute 'split' — you called a string method on a list, or similar. The message names the type you actually had, which usually tells you what went wrong earlier.
  • ModuleNotFoundError: No module named 'requests' — not installed, or installed into a different Python. That is lesson nine.
  • ZeroDivisionError — you divided by a count that turned out to be zero.
  • IndentationError / TabError — spacing is inconsistent. Pick four spaces and never mix in tabs.

How to work through one

  1. Read the bottom line. That is what happened.
  2. Find the lowest block naming your file. That is where.
  3. Look at the values, not the code. Print them just above the failing line: print(repr(name), bills.keys()). repr shows quotes and hidden spaces that print hides.
  4. Change one thing. Run again.

When you ask another person, or an AI assistant, paste the whole traceback, not just the last line. The chain of calls is usually where the answer is, and the last line alone is often unanswerable.

Try this now

Run the budget.py above exactly as written. Then change "rent" to "transport" and run again. Then delete the return from total_for and run again, and read the new error type carefully.

The one thing to keep

Read a traceback bottom line first for what broke, then the lowest block of your own code for where.

Before you move on

Given the traceback above, a student says: "Line 8 is the broken line, so I will rewrite line 8." What is the better reading?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly