SECTION 1
Historical Context & Motivation
Every programmer, from absolute beginners to seasoned professionals, encounters errors — sometimes called bugs — in their code. The word "bug" itself has a storied history in computing, and the practice of finding and fixing errors has evolved alongside programming languages themselves. Understanding how the computing community learned to classify errors helps you appreciate why we still sort them into three distinct categories today.
1947 • The First Literal "Bug"
1950s • Early Compilers & Syntax Checking
1960s • Runtime Errors Gain a Name
1972 • Logic Errors & Software Engineering
1991 • Python's Friendly Error Messages
Over decades of programming, the community settled on three broad categories of errors: those the language catches before running your code, those that crash during execution, and those that silently produce incorrect output. The key question this lesson addresses is: how do you tell them apart, and what do you do about each one?
SECTION 2
Core Principles & Definitions
Before you can fix a problem, you need to diagnose it correctly. Just as a doctor classifies symptoms before prescribing treatment, a programmer classifies errors before debugging. Python errors fall into three fundamental types, each occurring at a different stage of your program's lifecycle.
Syntax Error
Runtime Error
Logic Error
KEY TAKEAWAY
SECTION 3
Visual Explanation
As the diagram illustrates, each error type corresponds to a different phase of your program's life. When you press "Run," Python first reads (parses) your entire file to check that the grammar is valid. If it finds a broken rule, it stops immediately with a SyntaxError — your code never even starts executing. If the grammar checks out, Python begins executing your code line by line. An instruction that is grammatically correct can still fail at this stage, producing a runtime error like ZeroDivisionError or IndexError. Finally, if every line runs without crashing, you might still get the wrong answer due to a logic error — and Python won't warn you at all.
SECTION 4
How Python Detects Each Error Type
Syntax Errors: The Parser's Job
When you run a Python file, the interpreter first converts your source code into an internal representation called an Abstract Syntax Tree (AST). During this process, the parser checks every line against Python's grammar rules. If it encounters something it doesn't understand — like a missing colon after an if statement or mismatched quotes — it raises a SyntaxError and points to the approximate location of the mistake with a caret (^) symbol.
Common Syntax Errors in Python
if, for, while, and def statements; unmatched parentheses, brackets, or quotes; incorrect indentation; using = instead of == in comparisons; and misspelling keywords like retrun instead of return.Runtime Errors: The Executor's Problem
Once the code passes the parser, Python begins running it line by line. A runtime error (also called an exception) occurs when an instruction is grammatically correct but asks the computer to do something impossible or undefined. Python names these errors precisely: a ZeroDivisionError means you tried to divide by zero, a TypeError means you mixed incompatible data types, and a NameError means you used a variable that hasn't been defined. The program halts at the exact line where the error occurs and prints a traceback showing the chain of function calls that led to the crash.
Logic Errors: The Programmer's Blind Spot
A logic error is the sneakiest type because Python provides absolutely no error message. The code is valid, runs to completion, and produces output — but that output is wrong. These errors stem from mistakes in your algorithm or reasoning, such as using the wrong formula, placing a statement inside a loop when it should be outside, or using > when you meant >=. To catch logic errors, you must test your program with known inputs and compare the actual output to the expected output.
Why Logic Errors Are the Hardest to Fix
SECTION 5
Detailed Error Classification with Examples
Now that you understand the three categories conceptually, let's look at specific Python error names and code examples for each one. The table below maps common error names to their type and provides a quick code snippet showing what triggers each one.
| Error Type | Python Error Name | Example Code | What Went Wrong |
|---|---|---|---|
| Syntax | SyntaxError | if x == 5 | Missing colon at end of if statement |
| Syntax | IndentationError | def greet():\nprint('hi') | Body of function not indented |
| Runtime | ZeroDivisionError | result = 10 / 0 | Cannot divide by zero |
| Runtime | NameError | print(mesage) | Variable 'mesage' was never defined (typo) |
| Runtime | IndexError | lst = [1,2]; lst[5] | Index 5 doesn't exist in a 2-element list |
| Runtime | TypeError | 'age: ' + 17 | Cannot concatenate a string and an integer |
| Logic | (No error name) | avg = a + b / 2 | Should be (a + b) / 2 — order of operations |
| Logic | (No error name) | if score > 90: | Should be >= 90 if 90 qualifies for an A |
Common Python errors organized by type
Notice the pattern in the comparison above: the later an error is caught, the harder it is to fix. Syntax errors are caught immediately with a clear message and caret pointing to the problem. Runtime errors give you a traceback, but the real cause might not be on the exact line that crashed. Logic errors provide no error message at all, meaning you have to rely on testing and careful reasoning to track them down.
SECTION 6
Worked Example: Diagnosing Errors in a Program
Let's walk through a short Python program that is supposed to calculate the average of three test scores. The original code has one error of each type. We'll identify, classify, and fix each one.
Finding and Fixing All Three Error Types
- 1
Step 1 — Read the Original Code
Here is the buggy program:score1 = 85score2 = 90score3 = int(input("Enter score 3: ")average = score1 + score2 + score3 / 3print("Average: " + average)Our goal is to find all three error types before running the program. - 2
Step 2 — Identify the Syntax Error
Look at line 3:score3 = int(input("Enter score 3: "). Count the parentheses — there are three opening parentheses but only two closing ones. Python's parser will catch this and report aSyntaxErrorbefore the program starts.Fix: Add the missing closing parenthesis →score3 = int(input("Enter score 3: ")) - 3
Step 3 — Identify the Runtime Error
After fixing the syntax error, the program will run. Look at line 5:print("Average: " + average). The variableaverageis a number (float or int), and you cannot concatenate a string with a number using+in Python. This will raise aTypeErrorwhen the program reaches that line.Fix: Convert the number to a string →print("Average: " + str(average)) - 4
Step 4 — Identify the Logic Error
After fixing both previous errors, the program runs and prints a result. But look at line 4:average = score1 + score2 + score3 / 3. Due to Python's order of operations,score3 / 3is calculated first, and then added toscore1andscore2. If all three scores are 90, this gives 90 + 90 + 30 = 210 instead of the correct average of 90. Python won't complain — it just gives the wrong answer.Fix: Add parentheses →average = (score1 + score2 + score3) / 3 - 5
Step 5 — Verify the Corrected Program
The corrected program:score1 = 85score2 = 90score3 = int(input("Enter score 3: "))average = (score1 + score2 + score3) / 3print("Average: " + str(average))Test it with score3 = 95: the average should be (85 + 90 + 95) / 3 = 90.0. If the program outputs 90.0, all three bugs are fixed.Expected output:Average: 90.0✅
SECTION 7
Comparing Error Types: Strengths & Strategies
Each error type requires a different debugging strategy. Knowing which approach to use saves time and reduces frustration. The table below summarizes what to look for and how to fix each type.
| Feature | Syntax Error | Runtime Error | Logic Error |
|---|---|---|---|
| Detected by | Python's parser | Python's executor | You (the programmer) |
| When | Before any code runs | When the faulty line executes | When you check output |
| Error message? | Yes — SyntaxError with caret | Yes — named exception with traceback | No message at all |
| Fix strategy | Read the error message, check the indicated line and the line above it | Read the traceback from bottom to top, add input validation or type conversion | Test with known inputs, use print statements or a debugger, trace through code by hand |
| Prevention | Use an IDE with syntax highlighting and linting | Validate user input, use try/except blocks | Plan your algorithm before coding, write test cases |
Debugging strategy comparison for each error type
KEY TAKEAWAY
SECTION 8
Connection to Advanced Error Handling
Understanding the three error types is just the beginning. As you advance in Python, you'll learn techniques specifically designed to handle and even prevent each type. The table below previews how beginners and more advanced programmers deal with errors differently.
| Concept | What You Learn Now | What Comes Next |
|---|---|---|
| Syntax Errors | Read the SyntaxError message and fix the typo | Use linters (like pylint or flake8) that catch errors in real time as you type |
| Runtime Errors | Read the traceback and fix the crash | Use try/except blocks to gracefully handle errors, write custom exception classes |
| Logic Errors | Use print statements to check intermediate values | Write unit tests with frameworks like unittest or pytest to automatically verify correctness |
| Overall Approach | Fix errors one at a time as they appear | Practice test-driven development (TDD) — write tests before code to prevent logic errors |
From beginner error fixing to professional error handling
In more advanced courses, you'll discover that Python's exception handling system with try, except, finally, and raise gives you powerful tools to anticipate runtime errors and respond gracefully instead of crashing. You'll also learn to write automated tests — small programs that check whether your main program produces the right output for dozens or hundreds of input cases. These skills build directly on the error classification you're learning today.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
Show answer
Question 2: BASIC CALCULATION
print("Hello World"
(b) x = int("abc")
(c) A program that should calculate the area of a circle using area = 2 * 3.14 * r instead of area = 3.14 * r ** 2Show answer
Question 3: INTERMEDIATE
num = input("Enter a number: ")
if num > 0
print("Positive")
elif num = 0:
print("Zero")
else:
print("Negative")Show answer
if num > 0:. Second, line 4 uses = (assignment) instead of == (comparison) — also a syntax error; fix it to elif num == 0:. Third, line 1 stores the input as a string (since input() always returns a string), so comparing it with > to an integer will cause a runtime TypeError. Fix it with num = int(input("Enter a number: ")) or num = float(input("Enter a number: ")).Question 4: APPLIED
grades = [88, 92, 75, 95, 80]
total = 0
for g in grades:
total = total + g
average = total / len(grades)
print(average)
Explain what type of error this is, why the result is wrong, and how to fix it.Show answer
average = total / len(grades) is indented inside the for loop, so the average is recalculated on every iteration while the total is still being built up. By coincidence the final iteration does compute the correct value here (because total equals the full sum on the last pass), but the indentation reveals a misunderstanding. In more complex programs, placing the averaging step inside the loop would waste computation and could lead to using a premature average. The fix is to un-indent the average line so it executes only after the loop finishes: move average = total / len(grades) to the same indentation level as print(average). Actually, in this specific example the printed answer happens to be correct (86.0), but the program is logically inefficient and would produce wrong intermediate averages if used inside the loop for other purposes.Question 5: CRITICAL THINKING
Show answer
result = 100 / x. This has no syntax errors. If x = 5, it runs perfectly and produces 20.0. If x = 0, it crashes with a ZeroDivisionError. The exact same line of code behaves differently depending on the value of x at the time of execution. This demonstrates that runtime errors are context-dependent — they depend on the data flowing through the program, not just the code itself. This is precisely why testing with multiple inputs is essential: a program that works for one test case might crash or give wrong answers for another. Professional developers use edge cases (like zero, negative numbers, empty strings, or very large values) specifically to hunt for runtime errors that only appear under unusual conditions.SUMMARY
Lesson Summary
Summary
Python programs can contain three types of errors. Syntax errors violate the language's grammar rules and are caught by the parser before any code runs — they produce a SyntaxError message with a caret pointing to the problem. Runtime errors (exceptions) occur during execution when a valid instruction encounters an impossible operation, such as dividing by zero or accessing a nonexistent list index. Python names these precisely (ZeroDivisionError, TypeError, IndexError) and provides a traceback showing the chain of calls.
Logic errors are the trickiest: the program runs without crashing but produces incorrect results because the algorithm or formula is wrong. Python provides no error message for logic errors, so the only way to detect them is to test with known inputs and compare actual output to expected output. Remember: the later an error is caught in the program lifecycle, the harder it is to fix. Building the habit of reading error messages carefully, using print() statements for debugging, and testing with multiple inputs will make you a much more effective programmer.