# 15 Common Errors in Python and How to Fix Them

When building Python applications, it's a given that you'll run into errors.
Learning to identify and fix these errors is essential for effective debugging,
time-saving, and more importantly, avoiding such errors in the future.

This article presents a collection of 15 frequent Python errors and their
solutions. Although this list doesn't encompass all possible Python errors, it
aims to acquaint you with common problems, equipping you to deal with them as
they arise.

<iframe width="100%" height="315" src="https://www.youtube.com/embed/mvWYdrn7m2c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## 1. SyntaxError

`SyntaxError` is a common error that occurs when the Python interpreter parses
your code and finds incorrect code that does not conform to the syntax rules.
Some common causes of `SyntaxError` include:

- Unclosed strings
- Indentation issues
- Misusing the assignment operator (`=`)
- Misspelling Python keywords
- Missing brackets, parentheses, or braces
- Using newer Python syntax on an old version of Python.

When this error occurs, a traceback is produced to help you determine where the
problem is. Take the following example:

```python
employees = {"pam" 30,
             "jim": 28}

for name, age in employees.items():
    print(f"{name.capitalize()} is {age} years old.")
```

On line 1, the syntax is invalid because the dictionary's first property lacks a
colon (`:`) to separate the property `"pam"` and the value `30`. When the code
is executed, the following traceback is produced:

```text
[output]
File "/home/stanley/code_samples/main.py", line 1
    employees = {"pam" 30,
                 ^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
```

The traceback message has multiple carets (`^`) showing where the invalid syntax
was encountered. While it sometimes might not pinpoint the exact location, it
will usually hint at the issue's probable location.

To address this issue, carefully consider the following information in the
traceback:

- File name
- Line number
- Location indicated by the caret (^)
- Error message, which can offer insights into the nature of the problem.
- The question added at the end of the error message provides valuable context.

To catch syntax errors before you execute the code, configure a linter within
your code editor, such as [Pylint](https://pypi.org/project/pylint/),
[Flake8](https://flake8.pycqa.org/) to statically analyze the code.

In the screenshot below, Pylance is used to highlights problematic areas with a
red underline in VS Code:

![Screenshot of Pylance highlighting an error](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/44ba7203-d0ce-4d5e-b62a-6d6dd6343300/lg2x =938x236)

## 2. IndentationError

The `IndentationError` occurs in Python when there's an indentation issue in
your code. Common causes include mixing tabs with spaces, incorrect spacing,
incorrectly nested blocks, or whitespace at the beginning of a statement or
file.

Consider the following example:

```python
if True:
print("Incorrectly indented")
```

This triggers a Python traceback similar to:

```text
[output]
  File "/home/stanley/code_samples/main.py", line 2
    print("Missing colon")
    ^
IndentationError: expected an indented block after 'if' statement on line 1
```

To address and prevent this issue, use an editor or IDE configured with
formatters like [Black](https://github.com/psf/black), which auto-formats your
code as you write. The previously mentioned Pylance linter can also help you
identify indentation errors:

![Screenshot of a linter identifying indentation errors](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/57c3d6cc-5733-46e1-7b10-139d5d808a00/lg2x =1118x608)

## 3. NameError

Python raises a `NameError` if you attempt to use an identifier that hasn't been
defined or might be out of scope. Other potential causes of a `NameError`
include referencing a variable before its assignment or misspelling an
identifier:

```python
print(name)
```

In this example, the `name` variable is not defined but is being accessed. As a
result, Python throws an exception:

```python
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    print(name)
NameError: name 'name' is not defined
```

To fix this problem, ensure that the variable or function name you want to use
has been defined. Check for spelling errors and ensure that the variable you
want to use is within the scope where it is being accessed.

Again, setting up a linter in your editor will help you catch such problems
error early in the development process:

![Screenshot of Pylance detecting a `NameError` in the code`](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/1bacae80-23ad-40b0-682b-0800a5e89200/orig =1022x248)

## 4. ValueError

The `ValueError` exception indicates that a function received an argument of the
correct data type; however, the value itself is invalid. For example, the
`int()` method accepts only integer string like `"42"`, and passing something
like `"forty-two"` will yield a `ValueError`:

```python
num = int("forty-two")
```

This leads to Python throwing an exception like this:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    num = int("forty-two")
ValueError: invalid literal for int() with base 10: 'forty-two'
```

Another common cause is passing an empty iterable to the `max()` or `min()`
built-in functions, e.g., `max([])`.

To resolve this issue, provide the correct data type and value as an argument to
the built-in functions. Check the documentation for the specific function you're
using to ensure compliance with expected input formats.

If applicable, consider using `try-except` blocks, to gracefully manage
potential user input errors and prevent `ValueError` occurrences that bring down
your entire program.

## 5. UnboundLocalError

The `UnboundLocalError` often occurs when you use a local variable within a
function or method before assigning a value to it. For example, referencing the
`name` variable before setting its value:

```python
def display_name():
    print(name)
    name = "John"

display_name()
```

You will see an exception resembling this:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 5, in <module>
    display_name()
  File "/home/stanley/code_samples/main.py", line 2, in display_name
    print(name)
UnboundLocalError: local variable 'name' referenced before assignment
```

Other common causes for this error include:

- A local variable in a function having the same name as a global variable,
  known as
  [shadowing a global variable](https://en.wikipedia.org/wiki/Variable_shadowing#:~:text=In%20computer%20programming%2C%20variable%20shadowing,is%20known%20as%20name%20masking).
- Using the `del` operator on a local variable that you referenced later.

To fix `UnboundLocalError`:

- Assign values to local variables before referencing them.
- If caused by shadowing a global variable, use a name different from the global
  variable.
- Avoid using the `del` operator on variables you will reference later.

## 6. TypeError

A `TypeError` exception in Python indicates that you are performing an operation
that is not supported or appropriate for the object data type. For example,
trying to divide a string with an integer:

```python
print("hello" / 3)
```

This produces an exception that looks like the following:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    print("hello" / 3)
TypeError: unsupported operand type(s) for /: 'str' and 'int'
```

This exception can also occur in situations like trying to loop over a
non-iterable (such as a float or integer) or using incorrect argument types for
built-in methods (like passing an integer to `len(),` which expects an
iterable). Furthermore, calling a function with fewer arguments than required or
comparing different data types can also lead to a `TypeError`.

To avoid these errors, ensure the following:

- Only iterate through iterable sequences.
- Use arguments that match the expected types in built-in functions.
- Supply the correct number of arguments when calling a function.
- Compare or convert to a common type when dealing with different data types.

[summary]
### See what happened right before a Python error
A traceback tells you where things broke, but logs tell you what led up to it. Centralize logs from all your Python services so you can search across deployments, correlate failures, and set alerts for repeating errors.
[Better Stack](https://betterstack.com/logs) makes this easy with fast search and built in monitoring.

<iframe width="100%" height="315" src="https://www.youtube.com/embed/XJv7ON314k4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
[/summary]

## 7. UnicodeError

A `UnicodeError` exception is raised when Python encounters encoding or decoding
issues. The reasons for this error include:

- Conflicts due to mixed encoding in the text.
- Incorrect byte order marks (BOM) leading to decoding errors.
- Use of unsupported or mismatched encoding schemes.
- Conflicts arising from different Unicode standards.
- Problems with surrogate pairs in UTF-16.
- Corrupted or incomplete byte sequences.

Consider this example where decoding a Unicode string with ASCII results in an
error:

```python
unicode_str = "\u1234\u5678\u90AB"
decoded_str = unicode_str.encode('utf-8')
print(decoded_str.decode('ascii'))
```

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 3, in <module>
    print(decoded_str.decode('ascii'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)
```

To mitigate such issues, use a reliable encoding like UTF-8 and ensure strings
are valid Unicode. Implementing error-handling strategies like try-except blocks
can also help manage encoding errors. Additionally, pay attention to Byte Order
Marks when working with files or data streams, and inspect the encoding and
character standards of external data sources.

## 8. ZeroDivisionError

Python raises the `ZeroDivisionError` exception when you attempt to divide a
number by zero:

```python
result = 5 / 0
print(result)
```

Python will throw the following exception:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    result = 5 / 0
ZeroDivisionError: division by zero
```

To fix this, avoid dividing numbers by zero. A strategy you can use is to check
if the divisor is zero:

```python
numerator = 5
denominator = 0

if denominator != 0:
    result = numerator / denominator
else:
    print("Division by zero avoided.")
```

This way, you can prevent the `ZeroDivisionError` by ensuring that the
denominator is not zero before performing the division.

## 9. FileNotFoundError

Python throws this exception when it attempts to perform file-related
operations, such as reading, writing, or deleting a file that does not exist in
the given location:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    with open('file_does_not_exist.txt', 'r') as file:
FileNotFoundError: [Errno 2] No such file or directory: 'file_does_not_exist.txt'
```

To fix this, ensure that the file exists at the given location. Also,
double-check the file path, file extension, and take into account relative or
absolute paths to the file.

Often, the program might receive incorrect file paths from users, which is
beyond your control. A good solution is to use a `try-except` block to handle
the `FileNotFoundError` so that the program doesn't crash:

```python
file_path = 'file_does_not_exist.txt'

try:
    with open(file_path, 'r') as file:
        content = file.read()
    # Additional file processing code can go here
except FileNotFoundError:
    print(f"The file '{file_path}' does not exist.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
```

This way, you can gracefully handle the absence of a file and prevent the
program from crashing.

## 10. ModuleNotFoundError

Python raises the `ModuleNotFoundError` when it can't import a module. This
issue may arise if the module isn't installed on your system or in the virtual
environment. Sometimes, the error could be due to an incorrect module path or
name. Additionally, this error occurs when importing from a package that lacks a
`__init__.py` file.

An example of this error's traceback is:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    import arrow
ModuleNotFoundError: No module named 'arrow'
```

To resolve this, first check if the module is installed, using `pip` for
third-party modules. Secondly, verify the accuracy of the module name and file
path, as errors here can lead to this issue. Lastly, ensure that Python packages
contain a `__init__.py` file, necessary for Python to recognize them as valid
packages.

## 11. MemoryError

A `MemoryError` in Python occurs when the system runs out of memory. This is
often caused by memory leaks where memory is continuously consumed without being
released, or by loading large files entirely instead of in smaller chunks.

For example, this code attempting to create a list with over a billion elements:

```python
large_list = [0] * (10**9)  # Attempting to create a list with more than a billion elements
```

leads to a `MemoryError`:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 1, in <module>
    large_list = [0] * (10**9)  # Attempting to create a list with more than a billion elements
MemoryError
```

To handle this, use memory profiling tools like Scalene to pinpoint the
memory-intensive parts of your program.

For Python servers, an interim fix could be setting up an auto-restart mechanism
that activates when memory usage crosses a certain limit. This approach can
temporarily alleviate memory leaks by periodically freeing up memory.

For large file operations, read files in smaller chunks. If the file is
line-based, iterate over discrete lines:

```python
with open("large_file.txt") as file:
    for line in file:
        print(line)
```

For single-line large files, consider using a Python generator. This method is
detailed in
[this Stack Overflow post](https://stackoverflow.com/questions/49752452/using-a-python-generator-to-process-large-text-files)
on processing large text files.

[summary]
### Catch Python exceptions in production with full context
Fixing errors locally is useful, but production failures need fast visibility. [Better Stack Error Tracking](https://betterstack.com/error-tracking) groups exceptions, highlights the most frequent stack traces, and can alert you on Slack or email when errors spike.
Start free and see your first grouped issues in minutes.
[/summary]

![Better Stack error tracking dashboard](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/91d5b92f-4597-40cd-c51e-5a73c7b2ee00/lg1x =2350x1002)



## 12. PermissionError

Python raises a `PermissionError` when it tries to execute an operation without
the required privileges, such as accessing or modifying restricted files or
directories. This error can also occur if a file is currently in use by another
program.

For example, trying to create a directory in a protected area like `/etc`:

```python
import os

os.mkdir("/etc/new_directory")
```

results in the following traceback:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 3, in <module>
    os.mkdir("/etc/new_directory")
PermissionError: [Errno 13] Permission denied: '/etc/new_directory'
```

To address a `PermissionError`, consider running your script with elevated
privileges using sudo, but be cautious as it can be risky.

Other solutions include modifying file or directory permissions with
`os.chmod()`, adjusting
[ACLs](https://www.redhat.com/sysadmin/linux-access-control-lists) using
`setfacl`, or moving the file/directory to a location with write permissions
using `shutil.move()`. The right solution here depends on your specific needs
and security considerations.

## 13. IndexError

An `IndexError` is often encountered when you attempt to access an index in a
sequence, such as a list, tuple, or string, and it is outside the valid range.
For instance, trying to access index 4 in a list with only three elements:

```python
numbers = [10, 20, 30]
numbers[4]
```

results in the following exception:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 2, in <module>
    numbers[4]
    ~~~~~~~^^^
IndexError: list index out of range
```

To prevent IndexError, ensure that the index you're accessing falls within the
sequence's valid range. This can be checked by comparing the index with the
sequence's length, obtainable using the len() method.

```python
numbers = [10, 20, 30]

# Ensure the index is within the range of the list
index = 4
if index < len(numbers):
    print(numbers[index])
```

## 14. KeyError

A `KeyError` in Python is raised when an attempt is made to access a dictionary
value using a key that doesn't exist. This error can occur if the key is
missing, if there's a typographical error, or if the dictionary is empty:

```python
my_dict = {'name': 'John', 'age': 25}
print(my_dict['location'])  # the 'location' key does not exist
```

The error message produced looks like this:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 2, in <module>
    print(my_dict['location'])  # the 'location' key does not exist
          ~~~~~~~^^^^^^^^^^^^
KeyError: 'location'
```

To avoid a `KeyError`, verify the presence of the key in the dictionary and
ensure there are no typos. Alternatively, use the `dict.get()` method, which can
return a default value if the key is not found:

```python
my_dict = {'name': 'John', 'age': 25}

print(my_dict.get('location', None))
```

For a more robust approach, use `get()` and handle the result accordingly:

```python
my_dict = {'name': 'John', 'age': 25}

location = my_dict.get('location')

if location is not None:
    print("Location:", location)
else:
    print("Location key not found in the dictionary.")
```

## 15. AttributeError

An AttributeError in Python is raised when there's an attempt to access or
utilize an attribute that an object or class doesn't possess. For instance,
since a list lacks the lower() method:

```python
my_list = [1, 2, 3]
print(my_list.lower())
```

This attempt results in the following error message:

```text
[output]
Traceback (most recent call last):
  File "/home/stanley/code_samples/main.py", line 2, in <module>
    print(my_list.lower())
          ^^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'lower'
```

To prevent this error, ensure that you're using attributes and methods that are
actually available for the given object. This can be confirmed by consulting the
object's documentation. Additionally, verify the correct spelling of the
attribute names.

You can also use tools like [Mypy](https://mypy-lang.org/) for static analysis
to detect such issues early. Mypy would indicate a problem in the above code as
follows:

```text
[output]
main.py:2: error: "list[int]" has no attribute "lower"  [attr-defined]
Found 1 error in 1 file (checked 1 source file)
```
## Dealing with Python errors in production

While we have explored common Python errors and their solutions, it is important to recognize that errors are inevitable in any sufficiently complex program. What matters in production is how quickly you can answer three questions: what broke, where it is happening, and what changed.

A practical way to shorten that loop is to pair good application logging with a setup that centralizes and visualizes your logs, so you can investigate incidents without SSHing into boxes or hunting for the right file.

Python offers several logging frameworks you can integrate into your application. Here is a minimal example using the standard library:

```python
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

try:
    1 / 0
except ZeroDivisionError as e:
    logger.exception(e)
```

**Learn more**: [A Comprehensive Guide to Logging in Python](https://betterstack.com/community/guides/logging/how-to-start-logging-with-python/)

Once your app is producing useful logs, the next step is shipping them somewhere central so they are searchable and available even if a server dies or a container restarts. That is where a collector helps.

### Ship logs reliably with a collector

In production you want log shipping to be boring. A collector runs alongside your application, collects logs from the sources you care about, enriches them with helpful metadata like host, service, and environment, and forwards everything to a central place. This is what makes it possible to debug across multiple machines, keep a consistent format, and avoid losing logs during spikes.

<iframe width="100%" height="315" src="https://www.youtube.com/embed/_pv2tKoBnGo" title="Ship logs to Better Stack with the collector" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

### Follow incidents in real time with Live Tail

Once logs are centralized, you can go beyond tailing a single file or running `journalctl --follow` on one server. Live Tail lets you watch events in real time across all machines, filter as new logs arrive, and jump into surrounding context with a click. It is ideal for active incidents, deploy verification, and tracking down intermittent errors.

<iframe width="100%" height="315" src="https://www.youtube.com/embed/XJv7ON314k4" title="Better Stack Live Tail walkthrough" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

### Visualize patterns so you can spot spikes and trends

After the incident is contained, the next challenge is understanding impact and preventing repeats. Visualizations help you move from individual log lines to higher level signals: error rate over time, top exception messages, which hosts are affected, and whether a regression started right after a release. Instead of searching manually, you can turn recurring questions into dashboards and keep an eye on trends.

<iframe width="100%" height="315" src="https://www.youtube.com/embed/xmqvQqPkH24" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

If you want to try it, [sign up for a free account](https://uptime.betterstack.com/users/sign-up), connect your first source, and you will have a single place to collect, live tail, and visualize your production errors.

## Final thoughts

Understanding the common causes of Python errors and how to address them is
crucial for efficient problem-solving. In this article, we explored 15 common
errors in Python and discussed various strategies to resolve them.

For further exploration,
[the Python documentation](https://docs.python.org/3/tutorial/errors.html)
offers detailed information on exceptions and custom exception creation.

You should also check out our [logging guides](https://betterstack.com/community/guides/logging/) for further guidance on
how to create a comprehensive logging strategy for your Python applications.

Thanks for reading, and happy coding!