Errors Everywhere#

# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "numpy",
#     "matplotlib",
# ]
# ///

A Short Overview of Error Messages in Python#

In this notebook, we explore common Python errors through short, live-coded examples. The goal is not just to recognise these errors, but to understand how Python helps you debug them.

There are two key ideas to keep in mind:

  • Error type tells you what went wrong (e.g. SyntaxError, TypeError, IndexError).

  • Traceback tells you where it went wrong — it points to the exact line and function where the problem occurred. Understanding these two aspects will help you fix bugs faster and read error messages more confidently. Let’s get started.

Error Types and Tracebacks#

When Python encounters an error, it raises an exception.

_IncompleteInputError#

Close parenthesis are missing.

print('hello'
  Cell In[2], line 1
    print('hello'
                 ^
SyntaxError: incomplete input

SyntaxError#

Unterminated string. The closing quote is missing.

print('error)
  Cell In[44], line 1
    print('error)
          ^
SyntaxError: unterminated string literal (detected at line 1)

SyntaxError#

The first line of the function definition requires a colon at the end.

def cool_function(a, b)
    return a + b
  Cell In[45], line 1
    def cool_function(a, b)
                           ^
SyntaxError: expected ':'

IndentationError#

The return statement must be indented.

def cool_function_final(a, b):
return a + b
  Cell In[46], line 2
    return a + b
    ^
IndentationError: expected an indented block after function definition on line 1

TypeError#

Can’t add a string and an integer without conversion.

a = 2
b = '2'
a + b 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[48], line 3
      1 a = 2
      2 b = '2'
----> 3 a + b 

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

ValueError#

‘one’ can’t be converted to an integer.

int("one")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[50], line 1
----> 1 int("one")

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

IndexError#

We’re trying to access a list index that doesn’t exist.

my_list = [1, 2, 3]
print(my_list[10])                   
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[51], line 2
      1 my_list = [1, 2, 3]
----> 2 print(my_list[10])                   

IndexError: list index out of range

KeyError#

The dictionary key ‘b’ doesn’t exist.

my_dict = {"a": 1}
print(my_dict["b"])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[52], line 2
      1 my_dict = {"a": 1}
----> 2 print(my_dict["b"])

KeyError: 'b'

FileNotFoundError#

Trying to load a file that probably doesn’t exist.

import numpy as np
x = np.load('data.npy')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[53], line 2
      1 import numpy as np
----> 2 x = np.load('data.npy')

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/numpy/lib/_npyio_impl.py:454, in load(file, mmap_mode, allow_pickle, fix_imports, encoding, max_header_size)
    452     own_fid = False
    453 else:
--> 454     fid = stack.enter_context(open(os.fspath(file), "rb"))
    455     own_fid = True
    457 # Code to distinguish from NumPy binary files and pickles.

FileNotFoundError: [Errno 2] No such file or directory: 'data.npy'

Tracebacks - localising the error#

Understanding where in the code the error was raised is as important as understanding what the error is. Every error message will tell you the exact line of code that raised the error. Here explore how to read them.

ZeroDivisionError#

Division by zero is undefined. Traceback shows which line caused it; line 2. Note that line 3 would raise the same error, but we only see the error caused by line 2 since the code execution is stopped when the first error is encountered.

x = 10 * 0
y = 10 / 0
z = 10 / 0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[4], line 2
      1 x = 10 * 0
----> 2 y = 10 / 0
      3 z = 10 / 0

ZeroDivisionError: division by zero

No error (yet)#

Function is defined, but contains a reference to an undefined variable.

def another_function(x, y):
    return undeclared_variable

NameError#

Calling the function reveals the undefined variable. Traceback shows that the error was caused by calling the another_function, where in the notebook that function lives (the number in square brackets), and which line in the function caused the error.

another_function(1, 2)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[56], line 1
----> 1 another_function(1, 2)

Cell In[55], line 2, in another_function(x, y)
      1 def another_function(x, y):
----> 2     return undeclared_variable

NameError: name 'undeclared_variable' is not defined

NameError#

Typo in variable name inside nested functions. Traceback shows nested calls and leads us through this more complicated code to the error.

import matplotlib.pyplot as plt
import numpy as np

def draw_branch(x, y, angle, length, depth, lines):
    if depth == 0:
        return
    x2 = x + np.cos(angle) * length
    y2 = y + np.sin(angle) * length
    lines.append(((x, x2), (y, yii)))
    new_length = length * 0.7
    draw_branch(x2, y2, angle + np.pi / 6, new_length, depth - 1, lines)
    draw_branch(x2, y2, angle - np.pi / 4, new_length, depth - 1, lines)

def plot_tree():
    lines = []
    draw_branch(0, 0, np.pi / 2, 1, 6, lines)
    for (x, y) in lines:
        plt.plot(x, y, 'k-', lw=1)
    plt.axis('off')
    plt.gca().set_aspect('equal')
    plt.show()

plot_tree()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[57], line 23
     20     plt.gca().set_aspect('equal')
     21     plt.show()
---> 23 plot_tree()

Cell In[57], line 16, in plot_tree()
     14 def plot_tree():
     15     lines = []
---> 16     draw_branch(0, 0, np.pi / 2, 1, 6, lines)
     17     for (x, y) in lines:
     18         plt.plot(x, y, 'k-', lw=1)

Cell In[57], line 9, in draw_branch(x, y, angle, length, depth, lines)
      7 x2 = x + np.cos(angle) * length
      8 y2 = y + np.sin(angle) * length
----> 9 lines.append(((x, x2), (y, yii)))
     10 new_length = length * 0.7
     11 draw_branch(x2, y2, angle + np.pi / 6, new_length, depth - 1, lines)

NameError: name 'yii' is not defined

ValueError#

Invalid colormap. Error message is very long and not very helpful, but the developers added more details and suggests valid options.

import matplotlib.pyplot as plt
plt.imshow(np.zeros((10, 10)), cmap='error')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[41], line 2
      1 import matplotlib.pyplot as plt
----> 2 plt.imshow(np.zeros((10, 10)), cmap='error')

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/pyplot.py:3601, in imshow(X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, colorizer, origin, extent, interpolation_stage, filternorm, filterrad, resample, url, data, **kwargs)
   3579 @_copy_docstring_and_deprecators(Axes.imshow)
   3580 def imshow(
   3581     X: ArrayLike | PIL.Image.Image,
   (...)   3599     **kwargs,
   3600 ) -> AxesImage:
-> 3601     __ret = gca().imshow(
   3602         X,
   3603         cmap=cmap,
   3604         norm=norm,
   3605         aspect=aspect,
   3606         interpolation=interpolation,
   3607         alpha=alpha,
   3608         vmin=vmin,
   3609         vmax=vmax,
   3610         colorizer=colorizer,
   3611         origin=origin,
   3612         extent=extent,
   3613         interpolation_stage=interpolation_stage,
   3614         filternorm=filternorm,
   3615         filterrad=filterrad,
   3616         resample=resample,
   3617         url=url,
   3618         **({"data": data} if data is not None else {}),
   3619         **kwargs,
   3620     )
   3621     sci(__ret)
   3622     return __ret

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/__init__.py:1521, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
   1518 @functools.wraps(func)
   1519 def inner(ax, *args, data=None, **kwargs):
   1520     if data is None:
-> 1521         return func(
   1522             ax,
   1523             *map(cbook.sanitize_sequence, args),
   1524             **{k: cbook.sanitize_sequence(v) for k, v in kwargs.items()})
   1526     bound = new_sig.bind(ax, *args, **kwargs)
   1527     auto_label = (bound.arguments.get(label_namer)
   1528                   or bound.kwargs.get(label_namer))

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/axes/_axes.py:5965, in Axes.imshow(self, X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, colorizer, origin, extent, interpolation_stage, filternorm, filterrad, resample, url, **kwargs)
   5747 @_preprocess_data()
   5748 @_docstring.interpd
   5749 def imshow(self, X, cmap=None, norm=None, *, aspect=None,
   (...)   5752            interpolation_stage=None, filternorm=True, filterrad=4.0,
   5753            resample=None, url=None, **kwargs):
   5754     """
   5755     Display data as an image, i.e., on a 2D regular raster.
   5756 
   (...)   5963     (unassociated) alpha representation.
   5964     """
-> 5965     im = mimage.AxesImage(self, cmap=cmap, norm=norm, colorizer=colorizer,
   5966                           interpolation=interpolation, origin=origin,
   5967                           extent=extent, filternorm=filternorm,
   5968                           filterrad=filterrad, resample=resample,
   5969                           interpolation_stage=interpolation_stage,
   5970                           **kwargs)
   5972     if aspect is None and not (
   5973             im.is_transform_set()
   5974             and not im.get_transform().contains_branch(self.transData)):
   5975         aspect = mpl.rcParams['image.aspect']

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/image.py:884, in AxesImage.__init__(self, ax, cmap, norm, colorizer, interpolation, origin, extent, filternorm, filterrad, resample, interpolation_stage, **kwargs)
    867 def __init__(self, ax,
    868              *,
    869              cmap=None,
   (...)    879              **kwargs
    880              ):
    882     self._extent = extent
--> 884     super().__init__(
    885         ax,
    886         cmap=cmap,
    887         norm=norm,
    888         colorizer=colorizer,
    889         interpolation=interpolation,
    890         origin=origin,
    891         filternorm=filternorm,
    892         filterrad=filterrad,
    893         resample=resample,
    894         interpolation_stage=interpolation_stage,
    895         **kwargs
    896     )

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/image.py:263, in _ImageBase.__init__(self, ax, cmap, norm, colorizer, interpolation, origin, filternorm, filterrad, resample, interpolation_stage, **kwargs)
    250 def __init__(self, ax,
    251              cmap=None,
    252              norm=None,
   (...)    261              **kwargs
    262              ):
--> 263     super().__init__(self._get_colorizer(cmap, norm, colorizer))
    264     if origin is None:
    265         origin = mpl.rcParams['image.origin']

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/colorizer.py:610, in _ScalarMappable._get_colorizer(cmap, norm, colorizer)
    606     _ScalarMappable._check_exclusionary_keywords(
    607         Colorizer, cmap=cmap, norm=norm
    608     )
    609     return colorizer
--> 610 return Colorizer(cmap, norm)

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/colorizer.py:56, in Colorizer.__init__(self, cmap, norm)
     53 def __init__(self, cmap=None, norm=None):
     55     self._cmap = None
---> 56     self._set_cmap(cmap)
     58     self._id_norm = None
     59     self._norm = None

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/colorizer.py:237, in Colorizer._set_cmap(self, cmap)
    235 from matplotlib import cm
    236 in_init = self._cmap is None
--> 237 self._cmap = cm._ensure_cmap(cmap)
    238 if not in_init:
    239     self.changed()

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/cm.py:309, in _ensure_cmap(cmap)
    306 # use check_in_list to ensure type stability of the exception raised by
    307 # the internal usage of this (ValueError vs KeyError)
    308 if cmap_name not in _colormaps:
--> 309     _api.check_in_list(sorted(_colormaps), cmap=cmap_name)
    310 return mpl.colormaps[cmap_name]

File ~/.cache/uv/environments-v2/juv-tmp-q5418f1c-660e5b8f23e19f4b/lib/python3.13/site-packages/matplotlib/_api/__init__.py:130, in check_in_list(values, _print_supported_values, **kwargs)
    128 if _print_supported_values:
    129     msg += f"; supported values are {', '.join(map(repr, values))}"
--> 130 raise ValueError(msg)

ValueError: 'error' is not a valid value for cmap; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Grays', 'Grays_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'berlin', 'berlin_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_grey', 'gist_grey_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gist_yerg', 'gist_yerg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'grey', 'grey_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'managua', 'managua_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'vanimo', 'vanimo_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
../../_images/b2e9b2cc56a39a304c8e8f9c2f13eec67e20044e1ae964d3c0d5b1c1f239dfdc.png

Wrapping Up#

Errors are not your enemy—they’re your most helpful feedback while programming. By learning to read both the type of error (what went wrong) and the traceback (where it went wrong), you gain a powerful tool for debugging and understanding your code. As you write more complex programs, especially with functions and libraries, tracebacks will guide you through layers of execution to pinpoint the real issue.

Remember: every programmer sees errors. Skilled programmers just read them better.