← Learning center

Understanding Python error messages and stack traces

It's important to understand what your application's error messages are telling you when debugging an issue.

In this article, we'll explore common Python error types and what each one reveals about your application when encountered.

We'll also show you how AppSignal helps thousands of developers capture and monitor these errors in real-time, giving you the insights needed to quickly pinpoint problems.

How to read an error message

Error messages are most often output in the following format:

Python
File, line 1, Context ErrorType: error message

For example, considering the following example:

Python
File "/../maths_is_hard.py", line 1, in <module> print(f"{x} divided by {y} is {x / y}") NameError: name 'x' is not defined

We can deduce the following:

  1. Error location: line 1 of the maths_is_hard.py file
  2. Error type: NameError
  3. Error Message: name 'x' is not defined

Which can be understood as: "On line 1, of the maths_is_hard.py file, an undefined x variable was used."

With AppSignal, you can automatically capture and monitor errors, including their stack traces, giving you real-time visibility into issues as they occur:

Screenshot of error tracking in AppSignal

How to read a stack trace

Whenever an error occurs in your application, Python will raise an exception and log a stack trace, which you can then use to find the location of an error within your application's code.

In Python, if you try and divide a number by zero, you will raise a ZeroDivisionError. To demonstrate a stack trace, let's raise one:

Python
# maths_is_hard.py def divide(x, y): print(f"{x} divided by {y} is {x / y}") divide(8, 0)

In the above code snippet, we've created a function called divide(a, b), which will divide any two integers we provide it. Let's run the code in our terminal to raise ZeroDivisionError and print a stack trace:

Python
$ python maths_is_hard.py Traceback (most recent call last): File "/home/runner/python-test-repo/maths_is_hard.py", line 8, in <module> divide(8, 0) File "/home/runner/python-test-repo/maths_is_hard.py", line 3, in divide print(f"{x} divided by {y} is {x / y}") ZeroDivisionError: division by zero

So, what is our stack trace telling us? Let's look at it line per line:

  1. The first line tells us: On line 8 of maths_is_hard.py code was executed that resulted in a ZeroDivisionError, below the line it shows us the function: divide(0,8)
  2. The second line tells us: the error was raised on line 3 of the maths_is_hard.py file via the divide function. Indented, under, it shows us the code of that line.
  3. The third line tells us: the error type and error message.

We can use this stack trace to deduce where the error was raised in our code and where the method was called from. In the case of the example above, we know the issue was caused by 0 being passed as an argument on maths_is_hard.py:3.

When AppSignal captures an error, you can inspect critical error details, including the full backtrace, to quickly identify and resolve issues:

Screenshot of error and backtrace in AppSignal

We could then make sure not to pass 0 as an argument or modify our method to safely return a message if 0 is passed as an integer:

Python
# maths_is_hard.py def divide(x, y): if y > 0: print(f"{x} divided by {y} is {x / y}") else: print("You can't divide by 0") divide(8, 0)

Which would output the following when run:

Shell
$ python maths_is_hard.py You can't divide by 0

Good to know: We're using shorter stack traces here for brevity, but your application's stack trace will often be much longer. However, the same logic to reading stack traces applies, regardless of length.

How AppSignal helps you fix errors faster

AppSignal's Error reporting automatically captures error details, including stack traces, so you don't have to spend time manually digging through logs. With AppSignal, you get immediate insights and actionable data, empowering you to resolve issues faster.

FeatureWithout AppSignalWith AppSignal
Tracking errorsManually searching through logs and stack tracesAutomatically captured and organized by AppSignal
Error notificationsChecking logs manually for errorsInstant real-time alerts for any error
Context and metadataLimited details from the error message and stack traceRich context like with request data, tags, trends and more
Fixing errorsManually finding error causesAppSignal provides actionable insights for quick resolutions

Common error types

In any programming language, you'll encounter various types of errors that can halt your application's execution. Understanding these error types is crucial for debugging and improving the stability of your code. Below are some of the most common error types you'll likely come across when working with Python.

With AppSignal, you can easily monitor and categorize these errors in real-time, so you can quickly identify, diagnose, and fix issues in your application.

KeyError

A KeyError occurs when trying to access a key that does not exist with dict[key], for example, when trying to access the non-defined indian key in the below python_breed_count dict:

Python
> python_breed_count = { 'ball': 12, 'timor': 9, 'burmese': 2 } > python_breed_count['indian'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'indian'

Resolutions

Using in operator

We can use the in operator to check to see if a value is in a dict, and then execute specific logic when that condition is met:

Python
if 'burmese' in python_breed_count: print(f"There are {python_breed_count['burmese']} snakes in the plane")

Using Dict

You can always list the available keys using the keys() function:

Python
> python_breed_count.keys() dict_keys(['ball', 'timor', 'burmese'])

You could then use dict[key] to retrieve available key values:

Python
> python_breed_count['burmese'] 2

However, as the KeyError example shows, an exception is raised when a key the dict does not contain is called:

Python
> python_breed_count['carpet'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'carpet'

If we don't wish to raise an error in this use case, we can instead dict(key) to retrieve values. When a key is not present, none or a default value:

Python
> python_breed_count = { 'ball': 12, 'timor': 9, 'burmese': 2 } # does not throw error, returns None if the key is not present > python_breed_count.get('indian') # does not throw error, returns 0 if the key is not present > python_breed_count.get('indian', 0) 0

NameError

A NameError is raised when calling an attribute or function that is not defined.

For example, we want to assign a string to the attribute, title only we make a typo and accidentally assign it to an attribute incorrectly named titel, meaning when we call title in our code, we raise a NameError, because title is not defined.

Python
> titel = "Monty's Masterclass: Pythonic Puns and Pop Culture Parodies" > title Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'title' is not defined. Did you mean: 'titel'?

Resolution

To resolve this error, we need to make sure we are calling attributes and functions that are defined:

Python
> title = "Monty's Masterclass: Pythonic Puns and Pop Culture Parodies" > title "Monty's Masterclass: Pythonic Puns and Pop Culture Parodies"

UnicodeError

UnicodeEncodeError and UnicodeDecodeError are raised when Python cannot encode or decode from or to Unicode.

In the below example, we're trying to encode the string piñata to ASCII. Because ASCII codec does not support the ñ character a UnicodeEncodeError is raised:

Python
> partyGame = "Piñata" > encodedPartyGame = partyGame.encode('ascii') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character '\xf1' in position 2: ordinal not in range(128)

As you can see in the above error, ñ, known in unicode as /xf1 cannot be encoded.

Resolution

A solution is to use a codec that supports the character you want to encode. Let's try in UTF-8:

Python
> partyGame.encode('utf-8') b'Pi\xc3\xb1ata'

As you can see, piñata is successfully encoded into a UTF-8 byte string. Let's try and decode it:

Python
encodedPartyGame.decode('utf-8') 'Piñata'

We may, however, also encounter a situation where you need to decode a byte_string via a specific codec and encounter an error due to an unsupported character:

Python
> encodedPartyGame.decode('ascii') UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)

In this case, we can pass an error argument telling Python what to do when encountering a character it can't decode. The values are strict, replace, ignore, and backslashreplace. While strict will return a UnicodeDecodeError the other arguments allow you to handle the encoded character without raising an error:

Python
> encodedPartyGame.decode('ascii', 'replace') 'Pi��ata' > encodedPartyGame.decode('ascii', 'ignore') 'Piata' > encodedPartyGame.decode('ascii', 'backslashreplace') 'Pi\\xc3\\xb1ata'

We can also try replacing non-supported characters before encoding:

Python
> 'piñata'.replace('ñ', 'n').encode('ASCII') b'Pinata'

TypeError

A TypeError occurs when an object is the wrong type for the action you are attempting to execute. For example, when trying to add an integer to a string:

Python
> "1" + 2 TypeError: can only concatenate str (not "int") to str

Resolution

As 1 is a string, it has no numerical value and can't be added to another integer. To be added successfully, it must first be converted into an integer, and we can do this using Python's int() function.

Python
> int('1') + 2 3

Note that we can only convert textual representations of integers to integer objects, not strings. Trying to convert a string to an integer would raise a ValueError.

ValueError

A ValueError occurs when a function is called with the correct argument type but the wrong value.

For example, Python's int() function, which converts strings of integers into integer objects, expects a string argument. However, the string must be a textual representation of an integer:

Python
> int('one') ValueError: invalid literal for int() with base 10: 'one'

Resolution

In this case, to resolve the error, we need to make sure we pass the correct value to the int() function:

Python
> int('1') 1

If you need clarification on what values a function requires, access the function in your application or read the relevant documentation. For example, when looking at Python's documentation for the int() function we can read that by default, the function uses base 10, meaning the string can only contain digits between 0-9.

Never miss an exception with AppSignal

With AppSignal's error reporting, you can automatically capture and get notified about errors as they happen, helping you resolve issues quickly and stay focused on building great software.

Graph showing Python error in AppSignal

Our Error Reporting is just one of many developer-focused features designed to make monitoring seamless. Developers love using AppSignal because we offer:

  • A simple, intuitive interface that anyone can navigate.
  • Transparent, straightforward pricing.
  • Developer-first support tailored to your needs.

Ready to take control of your Python app's errors? Start your free trial with AppSignal today!

Start your free trial

Don’t let the bad bugs bite. Try AppSignal for free.

AppSignal offers a 30-day free trial, no credit card is required. All features are available in all plans. Start monitoring your application in just a few clicks!