Python Basics for Vibe Coders

Python Basics for Vibe Coders, Part 8: Read Error Messages from the Bottom Up

Read Python error messages (tracebacks) from the last line up: 6 common errors, friendlier 3.15 messages, try/except, and how to report errors to AI.

Python Basics for Vibe Coders, Part 8: Read Error Messages from the Bottom Up

When you vibe code, you see red error messages all the time. It's tempting to skip reading them and paste the whole thing into the AI. That works, but if you can read just the last line, you'll find the cause much faster and ask the AI a sharper question. This is Part 8 of the 10-part series "Python Basics for Vibe Coders," and it covers how to read error messages (tracebacks) and how to handle errors you can see coming with try / except. The examples are written for Python 3.15, and I ran them in Python 3.14.2 to check the results (I checked the messages that changed in 3.15 against the official docs).

Illustration of a dark console panel with empty horizontal bars, a magnifying glass lighting up the orange bar at the bottom, and a small warning triangle

Key Takeaways

  • An error isn't your program breaking. It's a clue from Python.
  • Read a traceback from the bottom line up. The last line tells you the type of error and the reason.
  • The File "...", line N lines above it tell you the file and line number where the error happened.
  • Use try / except ErrorName: only for errors you can predict. If you hide every error with a bare except:, you'll never find the real cause.

An error is your GPS saying "Road closed"

When your GPS tells you a road is closed, you can find another route. Error messages work the same way. Because they tell you what went wrong, you can fix it.

They're a bit like the red marks on a graded test, but friendlier. They don't just mark what's wrong; they tell you which line it happened on and what happened there.

How to read a Python error message (traceback)

If you try to turn text that isn't a number into an integer, you get an error. For example, if line 3 of a file called app.py contains int("three"), you'll see this message (the file path depends on your setup):

Traceback (most recent call last):
  File "app.py", line 3, in <module>
    number = int("three")
ValueError: invalid literal for int() with base 10: 'three'

(For some errors, Python adds a row of ~ and ^ marks under the code to point at the part that failed. This example doesn't get them.)

WhereWhat it saysHow to read it
Top lineTraceback (most recent call last):Just a heading that says "an error happened"
MiddleFile "app.py", line 3Which file and which line
Below thatnumber = int("three")The code that caused the problem
Last lineValueError: ...Error type: reason. Start reading here

The last line means "int() got the text 'three', which it can't convert." When an error happens inside a function, several File ... line ... lines stack up in the middle. The lower a line is, the closer it is to where the error actually happened.

Here are the error types you'll see most often, matched with the parts of this series where they come up.

ErrorCommon causeRelated part
SyntaxErrorInvalid syntax (a missing parenthesis, quote, or colon; mixing up = and ==)Parts 1 and 3
NameErrorA name you never created, or a typo (Print)Part 1
TypeErrorCalculating with values of different types ("20" + 1)Part 2
ValueErrorThe type is right but the value isn't (int("three"))This part
IndexErrorA position that doesn't exist in the listPart 5
KeyErrorA key that doesn't exist in the dictionaryPart 6

Friendlier messages in Python 3.15

Python 3.15 adds more messages that suggest the right name when you call something that doesn't exist. In the example from the official docs, using push on a list ends like this (the start of the traceback is omitted; see What's New in Python 3.15):

>>> [1, 2, 3].push(4)
AttributeError: 'list' object has no attribute 'push'. Did you mean '.append'?

When you see "Did you mean ...?", check that suggestion first. Python picked a candidate with a similar name, so it isn't always the right answer. push is the name used for JavaScript arrays, so you may see this message in code where habits from another language have crept in.

try / except: handling errors you can predict

Some errors you can see coming, like a user typing letters instead of a number. You can handle those ahead of time.

def to_number(text):
    try:
        return int(text)
    except ValueError:
        return None

print(to_number("42"))
print(to_number("three"))
42
None

If a ValueError happens while the code inside try is running, Python stops at that line and jumps straight to the code under except ValueError:. Any try code after the line that failed is skipped.

Common trap: is it safe to swallow every error with except:?

try:
    ...
except:
    pass

If you write except: with no error name and put pass (do nothing) under it, the program won't stop. That looks safe, but it also silently hides things like a NameError caused by a typo. The results are wrong, there's no error message at all, and you have no way to find the cause.

If you see except: or except Exception: pass in AI code, ask: "Which error were you expecting here? Change it to handle only that error." The rule is to name the error you're handling, like ValueError.

How to pass an error to the AI

  1. Paste the entire error message. If you only give it the last line, the AI can't tell which line the error came from.
  2. Read the last line first and add one line about what you think the cause is. For example: "I get a ValueError from int("three"). I think the user typed letters."
  3. Say what you were trying to do and what command you used to run it.
  4. Remove any API keys, passwords, or personal folder paths from the error message before you send it.

Check yourself

  1. Where should you look first in a traceback? → The error type and reason on the very last line. The top line is just a heading.
  2. If an error that except handles happens on the third line inside try, what happens? → Python stops at that line and goes straight to except. The program only ends right away when the error isn't handled.

Try it yourself

Write to_int(text, default=0), which takes a string and converts it to an integer, but gives back the default value 0 if that fails. If to_int("7") gives 7 and to_int("abc") gives 0, you've got it. If you get stuck, check the spelling of the error name after except and your indentation.

def to_int(text, default=0):
    try:
        return int(text)
    except ValueError:
        return default

print(to_int("7"))
print(to_int("abc"))
7
0

Previous and next

The full series list is at the end of Part 10.

Back to list