Python February 25, 2026 7 min read 26 views

Common Python Errors and How to Fix Them

From IndentationError to RecursionError—Python errors can be intimidating. Learn what causes the 8 most common exceptions and exactly how to fix them with practical debugging strategies.

Common Python Errors and How to Fix Them: A Debugging Guide for Students

 

You've been staring at the screen for twenty minutes. The code looks right. The logic makes sense. But the terminal keeps flashing that same red message: SyntaxError: expected ':' or maybe TypeError: unsupported operand type(s).

Frustration builds. You start randomly adding colons, removing spaces, or renaming variables—hoping something will stick.

We've all been there.

The problem with Python errors isn't that they appear—errors are a natural part of programming—it's that most beginners don't know how to read them. Error messages aren't the computer's way of saying "you failed." They're actually the most generous gift Python gives you: a detailed map pointing directly to what went wrong .

Why Understanding Errors Matters

Here's the truth: professional programmers encounter errors constantly. The difference between a novice and an experienced developer isn't error-free code—it's the ability to interpret and fix errors quickly.

Why does this matter for your grades and projects?

  1. Faster debugging: When you recognize an IndexError instantly, you stop guessing and start fixing
  2. Confidence: Errors stop feeling like failures and start feeling like puzzles
  3. Better code: Understanding edge cases helps you write more robust programs from the start
  4. Exam preparedness: Many practical exams test your ability to debug intentionally broken code

In this guide, we'll cover the eight most common Python errors you'll encounter in university projects, exactly what causes them, and the step-by-step fixes that work.


Step-by-Step Breakdown: 8 Common Python Errors and Their Fixes

1. IndentationError: The Whitespace Trap

What it looks like:
 

def hello():
print("Hello")  # Note the missing indent

# Output:
# IndentationError: expected an indented block

What's happening: Unlike other languages that use braces {}, Python uses indentation to define code blocks. When indentation is missing or inconsistent, Python doesn't know which code belongs where.

The fix:

def hello():
    print("Hello")  # Properly indented with 4 spaces

Pro tip: Configure your editor to insert 4 spaces when you press Tab. Mixing tabs and spaces creates an IndentationError: unindent does not match any outer indentation level . Pick one and stick with it.

2. NameError: The Undefined Variable

What it looks like:

print(message)

# Output:
# NameError: name 'message' is not defined

What's happening: You're trying to use a variable that hasn't been created yet, or you've misspelled an existing variable name . This also happens when you reference a variable outside its scope.

Common scenario:

def my_func():
    num = 10

print(num)  # NameError: num is defined inside the function, not outside

The fix: Define the variable before using it, or check your spelling. For scope issues, either return the value or define it in the outer scope.

3. TypeError: Operation Not Supported

What it looks like:

age = 25
message = "I am " + age + " years old."

# Output:
# TypeError: can only concatenate str (not "int") to str

What's happening: You're trying to perform an operation on incompatible data types. You can't add strings and integers, divide strings by numbers, or call non-function objects .

The fix: Convert types explicitly:

message = "I am " + str(age) + " years old."

Or use f-strings (Python 3.6+):

message = f"I am {age} years old."

4. IndexError: Out of Bounds

What it looks like:

fruits = ["apple", "banana", "cherry"]
print(fruits[3])

# Output:
# IndexError: list index out of range

What's happening: Lists, strings, and tuples are zero-indexed. With three items, valid indices are 0, 1, and 2. Index 3 doesn't exist .

The fix: Check your list length before accessing:

if len(fruits) > 3:
    print(fruits[3])
else:
    print("Index out of range")

Remember negative indexing: fruits[-1] gives "cherry" (last item), but fruits[-4] on a three-item list will also raise IndexError .

5. KeyError: Dictionary Key Missing

What it looks like:

student_grades = {"Alice": 95, "Bob": 88}
print(student_grades["Charlie"])

# Output:
# KeyError: 'Charlie'

What's happening: You're trying to access a dictionary key that doesn't exist .

The fix: Use .get() which returns None (or a default value) instead of crashing:

grade = student_grades.get("Charlie")  # Returns None
grade = student_grades.get("Charlie", 0)  # Returns 0 if key missing

Or check first:

if "Charlie" in student_grades:
    print(student_grades["Charlie"])

6. AttributeError: Missing Method or Property

What it looks like:

text = "hello world"
text.push("!")

# Output:
# AttributeError: 'str' object has no attribute 'push'

What's happening: You're trying to call a method that doesn't exist for that object type. Strings don't have a .push() method—lists do .

The fix: Use the correct method for the type:

text = text + "!"  # String concatenation
# Or
text += "!"

7. ImportError / ModuleNotFoundError: Missing Modules

What it looks like:

import non_existent_module

# Output:
# ModuleNotFoundError: No module named 'non_existent_module'

What's happening: Python can't find the module you're trying to import. Either it's not installed, the name is misspelled, or the module isn't in your Python path .

The fix:

  • Check spelling: import math not import maths
  • Install missing packages: pip install requests
  • For local modules, ensure the file exists and you're running from the correct directory

8. RecursionError: Too Deep

What it looks like:

def factorial(n):
    return n * factorial(n-1)  # No base case!

factorial(5)

# Output:
# RecursionError: maximum recursion depth exceeded

What's happening: A function calling itself without a stopping condition creates an infinite loop that eventually exceeds Python's recursion limit.

The fix: Always include a base case:

def factorial(n):
    if n <= 1:  # Base case
        return 1
    return n * factorial(n-1)

The Debugging Process: How to Fix Anything

When you encounter any error, follow this systematic approach :

1. Read the Error Message Carefully

The error message contains three critical pieces of information :

  • Error typeTypeErrorValueError, etc.
  • Error message: The specific problem
  • Traceback: The exact line number where it occurred

2. Make It Fail Every Time

A bug you can reproduce is a bug you can fix. If it's intermittent, isolate the conditions that cause it.

3. Change One Thing at a Time

Random changes create random results. Form a hypothesis ("I think this variable is the wrong type") and test it with a single change .

4. Use Print Statements Strategically

def divide(a, b):
    print(f"DEBUG: a={a}, b={b}, types: {type(a)}, {type(b)}")
    return a / b

5. Leverage Python's Built-in Debugger

Insert breakpoint() (Python 3.7+) to pause execution and inspect variables interactively

def process_data(data):
    breakpoint()  # Execution pauses here
    # Now you can type 'data' to see its value
    return [x * 2 for x in data]

6. Check Assumptions with Assertions

def calculate_average(numbers):
    assert len(numbers) > 0, "List cannot be empty"
    return sum(numbers) / len(numbers)

 

Still stuck on a persistent bug? Sometimes you need a fresh pair of eyes. Our experienced Python tutors can help you debug complex issues and teach you systematic problem-solving techniques. Book a tutoring session today and get unstuck in minutes.


Common Mistakes Students Make When Debugging

Even with the right tools, students often fall into these traps:

1. Ignoring the Error Message

The most common mistake: seeing red text and immediately looking away. Read the error. It tells you exactly what's wrong.

2. Changing Too Much at Once

When you change five things and the error disappears, you never learn what actually caused it. Worse, you might introduce new bugs you don't understand.

3. Skipping the Virtual Environment

Using the wrong Python version or missing dependencies causes mysterious ImportErrors and AttributeErrors. Always use a virtual environment .

4. Catching All Exceptions Blindly

try:
    risky_operation()
except:  # Don't do this!
    pass  # Now you'll never know what went wrong

This "universal catcher" hides every error, including critical ones. Always specify exception types .

5. Not Using Logging in Larger Projects

For projects with hundreds of lines, print() statements become clutter. Use the logging module for production-quality debugging .

import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug(f"User data: {user_data}")

FAQ: Common Python Error Questions

Q: Why does Python care so much about indentation?
A: Python uses indentation to define code blocks instead of braces {}. This forces clean, readable code. Every modern Python developer considers this a feature, not a limitation .

Q: What's the difference between IndexError and KeyError?
A: IndexError occurs with sequences (lists, tuples, strings) when using numeric indices out of range. KeyError occurs with dictionaries when using keys that don't exist .

Q: How do I know which exception type to catch?
A: Run your code once, let it crash, and read the error message. It tells you the exact exception type. Then wrap the problematic code in a try-except block with that specific exception .

Q: Should I always handle every possible error?
A: No. Catch errors you can meaningfully recover from. Let critical errors crash so you know they exist. In production, log them and fail gracefully .

Q: What's the best way to debug a loop that's not working?
A: Print the loop counter and key variables each iteration. Better yet, use breakpoint() inside the loop and step through manually .

Q: Why do I get NameError even though I defined the variable?
A: Check your scope. Variables defined inside functions aren't accessible outside unless returned. Variables defined in conditional blocks might not execute if the condition is false .

Q: How do I handle errors when reading files?
A: Use context managers (with statements) which automatically close files even if errors occur

try:
    with open('file.txt', 'r') as f:
        data = f.read()
except FileNotFoundError:
    print("File doesn't exist")
except PermissionError:
    print("Can't read file")

Bottom Line: Errors Are Teachers

Every error message is a learning opportunity. The more errors you encounter and understand, the better programmer you become. Python's error messages are among the most readable in any programming language—use them .

Remember the systematic approach:

  1. Read the full error message and traceback
  2. Identify the error type
  3. Locate the exact line
  4. Form a hypothesis
  5. Change one thing at a time
  6. Test thoroughly

Ready to master Python debugging and ace your assignments?

Whether you're stuck on a tricky RecursionError or want to learn professional debugging techniques, we're here to help.

Stop fighting with errors and start learning from them. Your grades—and your sanity—will thank you.


Related Posts

Binary Search Explained: Algorithm, Examples, & Edge Cases

Master the binary search algorithm with clear, step-by-step examples. Learn how to implement efficient searches in sorted arrays, avoid common …

Mar 11, 2026
How to Approach Hard LeetCode Problems | A Strategic Framework

Master the mental framework and strategies to confidently break down and solve even the most challenging LeetCode problems.

Mar 06, 2026
Two Pointer Technique | Master Array Problems in 8 Steps

Master the two-pointer technique to solve complex array and string problems efficiently. This guide breaks down patterns, provides step-by-step examples, …

Mar 11, 2026

Need Coding Help?

Get expert assistance with your programming assignments and projects.