MF 602
Fall 2021

Python Errors

This page contains a listing of common errors students find in their code. Feel free to use this list as a reference, consulting it when you have trouble understanding what an error means.

Note that when something goes wrong while the Python interpreter runs your program, the interpreter will stop and will produce a stack trace (also known as a traceback) that lists all functions that were running when the error occurred.1

For example, say that the expression a + 1 is executed before a has been given a value.

Traceback (most recent call last):
File "demo.py", line 1, in <module>
NameError: name 'a' is not defined

The last line gives us the type of the error (in this case, NameError), along with a description. On the second line, the stack trace lists the file and line number the interpreter was running when it encountered the error. Usually the error and description are enough to deduce what went wrong with your program, but sometimes the description is confusing. If you’re not sure what an error means, consult the following list.

SyntaxError

The most common type of error, a syntax error occurs when the interpreter is reading the Python file to determine if it is valid Python code and encounters something it doesn’t “understand”. The interpreter will check things like indentation, use of parentheses and square brackets, proper forms of if, elif, and else blocks, and so on.

For example, here’s a simple file that has a syntax error. In this case, the programmer has forgotten to add a closing square bracket to the definition of the list lst:

lst = [1, 2, 3
a = 2

When this is run by the Python interpreter, we get the following error message:

  File "issue.py", line 2
    a = 2
    ^
SyntaxError: invalid syntax

After Python is done with the first line, it expects to keep reading elements of lst (i.e., it expects to see a , and then another number). However, it sees that there is a variable assignment happening on the next line, and it stops with a syntax error.

It’s important to realize that, due to the way Python reads through the file, the interpreter reports that the syntax error is on line 2. However, line 2 is correct, and the error is being caused by a missing square bracket on the previous line!

See the Python documentation for more details.

IndentationError

Python uses indentation to determine which lines of code belong to other lines. For example, since it is possible to have many different function definitions in a Python file, the lines of code that belong to one function must be indented below the line containing def and the function’s name:

def my_function():
    print('note that these lines')
    print('are indented four spaces')
    print('from the def line')

In the example above (and in general), we can refer to the lines that have been indented under the def line to be children of the def line. Similarly, the def line is considered to be the parent of the lines indented underneath it. Here’s an illustrated example, which shows the parent/child relationships of each line:

All of the lines indented under the def line are children of the def line, with the exception of the lines indented deeper. The print("I can't believe it!") call is a child of the if line. The print('Me, too!') line is a child of the else line.

unindent does not match any outer indentation level

Before Python runs any code in your program, it will first determine the correct parent and children of each line. Python produces an IndentationError whenever it comes across a line for which it cannot determine the right parent to assign. For example:

def bad_indentation(num):
    if num < 10:
        a = 10
      b = 5

This code causes Python to output the following:

  File "<stdin>", line 4
    b = 5
        ^
IndentationError: unindent does not match any outer indentation level

Since the line containing b = 5 only has six spaces before it, Python couldn’t determine whether that line’s parent was the if line or the def line.

To fix this, either push the b = 5 line to the right two spaces (to place it under the if line) if you want it to run only when the condition is true, or pull the line to the left two spaces (to place it outside the if entirely) to make it run whether the condition is true or not.

expected an indented block

Lines that begin with def or if (for example) must have at least one child. This means that a function must have at least one line of code. It also means that a conditional must have at least one line of code to run if the condition is true. Take, for example, the following incorrect function:

def missing_block(num):
    if num > 10:

    elif num % 2 == 1:
        print("number can't be odd!")

Python produces the following output when the file containing this incorrect function is read:

  File "example.py", line 4
    elif num % 2 == 1:
       ^
IndentationError: expected an indented block

After Python reads the if line, it expects to see at least one child line following it. However, since the next non-empty line it reads is the elif line, and that line’s parent is the def line, the if line has no children, and Python reports that it expected some indented lines.

To fix this, either place at least one line of code as the if‘s child, or remove the if entirely. The same applies for any other type of line that must have at least one child (e.g., a def or for).

This error can also come up if the programmer forgets to indent a docstring. Docstrings must be in line with the rest of the code in a function. To fix this issue, indent the docstring.

unexpected indent

Python will also produce an IndentationError when it reads a line that is indented as if the line had some parent line, but Python couldn’t find any lines above to be its parent. A common special case of this indentation issue occurs when a line is indented by one or more spaces more than the previous line, and the previous line isn’t a def, if, elif, else, for, or while line (the kinds of lines that need children).

This often occurs by accident, if the programmer puts one too many spaces before a line. It can also happen when a docstring is placed on a different indentation level than the code inside of a function — to fix this, make sure the docstring is in line with the rest of the function’s code.

NameError

This error occurs when a name (a variable or function name) is used that Python does not know about. It can occur if a programmer changes a variable’s name but forgets to update the name everywhere in the Python file.

It can also occur in IDLE when a programmer is writing a Python file containing functions, and the programmer tries to access the functions from the shell without first pressing F5 or choosing “Run Module” from the Run menu.

It can also occur as the result of inconsistent indentation. For example:

def length(x):
    if x == '':
        return 0
    else:
        return 1 + length(x[1:])

    def caps(s):
        if s == '':
            return ''
        elif s[0] in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
            return 1 + caps(s[1:])
        else:
            return caps(s[1:])

You might expect that the function caps() could be accessed from the shell. However, the shell doesn’t know any function with the name caps(), because it’s defined inside the length() function. To fix this, the entire definition of the caps() function should be shifted left by four spaces.

It’s worth noting that it is sometimes useful to define functions inside of functions, especially if the outer function needs to return a function. However, in the example above, we want length() and caps() to be two, unrelated functions.

description

meaning

name 'x' is not defined

on this line, the variable name x is used, but Python has not yet seen an assignment statement for this variable

See the Python documentation for more details.

TypeError

This error occurs when a function or operator cannot be applied to the given values, due to the fact that the value’s type is inappropriate. This can happen when two incompatible types are used together, for example:

>>> "a" + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly

The TypeError is generated because addition (+) does not work between an integer and a string. However, note the description: it suggests a way to fix this error.

>>> "a" + str(2)
'a2'

This might not have been what the programmer intended, which is why Python stopped with a TypeError in the first place.

TypeError can come up in a variety of places, but it usually appears when a programmer’s assumption about the type of a value is incorrect (e.g., trying to manipulate an integer as if it were a list). The best way to diagnose these problems is to use Python’s built-in type() function to determine the type of the problematic variable’s value.

description

meaning

'function' object is not subscriptable

square brackets ([ and ]) were used next to the name of a function, but parentheses (( and )) must be used to call a function

'int' object is not subscriptable

similar to above; [ and ] were used on a variable that contains an integer, but [ and ] are used for getting an element or a slice of a sequence

Can't convert 'int' object to str implicitly

the + operator was used between a string and an integer; Python is not sure whether it should convert the integer into a string and do string concatenation, or convert the string into an integer and do regular addition

unsupported operand type(s) for +: 'int' and 'list'

this “unsupported operand type” error is very common, and is comes from the use of the + operator with two pieces of data whose types do not match; see the special note about this below

can only concatenate list (not "int") to list

exactly the same error as above, except the list is on the left and the integer is on the right; see the special note about this below

'float' object is not iterable

in a list comprehension, a non-sequence was used after the in keyword (e.g., [x for x in val] where val is 3.14 or some other number)

'int' object is not iterable

same as above, only where the value after the in keyword is an integer

object of type 'int' has no len()

the len() function was called with an integer, but len() only works with sequences

TypeError: unorderable types: NoneType() > int()

a relational operator like > or <= was used to compare a value that is None on the left and an integer on the right (e.g., None >= 0)

See the Python documentation for more details.

Issues when using the + operator

A common mistake made by beginning programmers is to use the + operator between values of incompatible types. For example, this straightforward use of + is just fine:

>>> 4 + 5
9

Let’s step through Python’s interpretation of this line. It first reads through the entire line and notices a use of +. It then considers the type of 4, which is int, and the type of 5, which is int. Since both numbers are the same type, and + is supported between ints, Python uses integer addition and comes up with 9.

However, take the following piece of code as an example:

>>> 0 + [1, 2, 3]

Python reads through the entire line and notices a use of +. It will consider the type of the left operand, 0 and conclude that it is an int. It then considers the type of the right operand, which is list. Python then produces an error, because it does not know how to add int and list. To be clear, Python will produce the following TypeError:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'

A slightly different error can be produced if the list is on the left and the non-list is on the right:

>>> [0] + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list

In general, Python only knows how to use + between two operands of the same type.2 So, how do we fix this? We should “wrap” the single int with square brackets to put it inside of a new list. Then Python will be able to use + between two operands of the same type (list!). Remember that, in this case, + between two lists will perform list concatenation: it will connect the two lists together:

>>> [0] + [1, 2, 3]
[0, 1, 2, 3]

Unexpected uses of None (NoneType)

Another common mistake occurs when programmers use the return value of a function they expect to return a string or integer value (for example), but Python outputs an error like the following:

Traceback (most recent call last):
  File "test.py", line 3, in outer_function
    return x + 1
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

Often, the source of this problem is a function that returns None, when some non-None value was expected. A function will return None when...

For example, take this function that, when given a number, returns ten times the number if the number is less than 10:

def mult_less_than_ten(n):
    if n < 10:
        return n * 10

The problem with this function is that it may not always return an integer value. If we pass in a number greater than or equal to 10, Python reaches the end of this function and automatically returns None.

Aside

This kind of function is called a partial function. In other programming languages (Java, for example), partial functions are not allowed. In those languages, your code won’t even run if a function might not return anything!

Python will not alert you to the fact that the function may not always return an integer; it usually becomes a problem when some other code makes use of this function.

def get_and_add_five():
    num = int(input('Enter an integer: '))
    num2 = mult_less_than_ten(num)
    return num2 + 5

What happens if the user enters a number greater than ten? The mult_less_than_ten() function will return None. Then None comes back to the get_and_add_five() function and is stored in num2. Python produces the error when it attempts to add None to 5.

IndexError

This error occurs when an index into a list or string is out of range. For example, attempting my_list[2] when the list my_list has zero, one, or two elements will produce an IndexError. This will also occur in the same way with strings.

Note that empty lists (i.e., []) and empty strings (i.e., '' or "") do not have an element or character at position 0. Attempting to index 0 with empty lists or strings will result in an IndexError. To determine if a variable contains the empty string or the empty list, try a direct comparison to '' or [] (i.e., s == '' or lst == []). You could also use the len() function, which returns 0 for empty sequences.

Note also that, when slicing a list or a string, IndexError will not be produced if any indices in the slice are out of bounds. See the transcript below for examples of this:

>>> my_list = [1, 2]
>>> my_list[:100]
[1, 2]
>>> my_list[100:]
[]
>>> my_list[100:200]
[]

description

meaning

string index out of range

square brackets ([ and ]) were used to access a particular character of a string, but the string doesn’t have a character at that position (the string is too short or the index is too large)

list index out of range

exactly the same problem as above, in the case of accessing an element of a list

See the Python documentation for more details.

RuntimeError

This error can be triggered by many problems, but it is most notably produced when a stack overflow occurs. Take the following simple example of a recursive function that will never terminate:

def forever():
    forever()

This function will fill up the Python interpreter’s stack until it runs out of memory space for another call to forever(). This can be seen by the traceback that Python prints (note that there were many, many more occurences of File "test.py", line 2, in forever that were not reproduced here, to save space):

...
  File "test.py", line 2, in forever
    forever()
  File "test.py", line 2, in forever
    forever()
  File "test.py", line 2, in forever
    forever()
  File "test.py", line 2, in forever
    forever()
  File "test.py", line 2, in forever
    forever()
RuntimeError: maximum recursion depth exceeded

In addition, the description here is helpful. If a programmer encounters RuntimeError with the description maximum recursion depth exceeded, the recursive function is probably missing a base case. However, it can still occur with a properly written recursive function, if that function is given a very large input.

description

meaning

maximum recursion depth exceeded

the number of function calls made in a row is too high; this could be infinite recursion or a sign that the input data is too large; this usually means that the base case is not triggering or the recursive case does not break the problem down into a smaller problem

See the Python documentation for more details.

ImportError

This error occurs when an import statement is used, but Python cannot find the Python module to import.

A common use of import statements is to gain access to a function that comes with Python, but isn’t available for use by default. For example, the functions that produce random values or make random choices from lists come from the random module. To use them, you must put the following line at the top of your file:

import random

After this line, you may use any function in the random module (e.g., choice()) by putting random. in front of the function’s name (i.e., random.choice(...)).

An ImportError occurs when Python cannot find the module you want to import. If you are trying to import a module that comes with Python (e.g., random, turtle, or functools), you may have misspelled the module’s name.

If you are trying to import a module from a file that you wrote, or from files we supplied you, you must ensure that the files you are trying to import are in the same folder as the file that is doing the import.

See the Python documentation for more details.

AttributeError

This error occurs when you try to access an attribute of an object, but one of these two conditions hold:

Keep in mind that attributes can be both variables and methods. In other words, you can get an AttributeError when you try to access a field of an object (i.e., a variable) that doesn’t exist, or when you try to call a nonexistent method.

See the Python documentation for more details.

ZeroDivisionError

As it sounds, this error is produced when a division by zero occurs in your code. To avoid this error, you should make sure you have nonzero divisors before performing a division.

See the Python documentation for more details.

UnicodeDecodeError

This error occurs when Python is reading from a file that contains special characters. Special characters are letters or symbols that fall outside the common English alphabet and are not standard punctuation and numbers. For example, a lower case A with an acute accent (á) is a special character. Special characters also include “curly” single and double quotation marks and the ellipsis character (…).

A simple way to fix this error is to remove the special characters from the file your program is reading. You can also add the encoding parameter with a value of 'utf-8' to the open() call you used to open the file. For example, you could use handle = open('filename.txt', 'r', encoding='utf-8'). This causes Python to recognize more kinds of characters when reading the file.

description

meaning

'ascii' codec can't decode byte ... in position ...

the file your Python program is reading contains a special character, but Python cannot read the character


Written by: Alexander Breen (CS111, Fall 2014, Spring 2015, Fall 2015, Spring 2016)


  1. In this course, we will study the runtime stack in detail as part of the unit on machine organization. 

  2. You might protest this if you’ve ever done 1.5 + 2 at the Python shell. Ultimately, however, Python is doing floating-point addition here. Python knows that it can convert 2 to 2.0 and then do 1.5 + 2.0 to produce a floating-point result.