IndexError: String Index out of Range

IndexError: String Index out of Range Featured Image

Surprise, surprise! We’re back with another article on a Python exception. Of course, this time we’re moving away from the SyntaxError and into a more specialized error, the IndexError, which is accompanied by various error messages. The error message we’ll be talking about today reads: IndexError: string index out of range.

In case you’re short on time, this IndexError arises when a string is accessed using an invalid index. For example, the string “VirtualFlat” has 11 characters. If a user were to try to access a character beyond this limit—say "VirtualFlat"[15]—an IndexError would arise.

In the remainder of this article, we’ll look at this IndexError more deeply. For instance, we’ll take a look at the IndexError broadly. Then, we’ll hone in on the specific message. After that, we’ll wrap things up with some potential solutions and offer up an opportunity to share your code if you’re still having trouble.

Table of Contents

What Is an IndexError?

According to Python documentation, an IndexError is raised whenever “a sequence subscript is out of range.” Of course, what does that really mean?

To break down this definition, we need to understand a few terms. First, a sequence is a list-like object where items are stored in order; think lists, strings, and tuples. In this context, a subscript is then another name for an item’s index.

In Python, for an index to be out of range, it must not exist. For example, if we had a string like “VirtualFlat”, a valid index would be any value less than the length of the string and greater than or equal to the negative length of the string:

# Declare some index
brand = "VirtualFlat"
is_valid_index = -len(brand) <= index < len(brand)

As we can see, the range of indices is actually asymmetric. This is because negative indexing starts from negative one—as opposed to zero during regular indexing.

On a side note, I probably should have represented the range mathematically, but I struggled to come up with a syntax where the length operator wasn’t the exact same operator as absolute value (i.e. |x|). Also, the lack of symmetry made the expression clunky either way. I would have preferred something like |index| < |brand|, but it ends up being -|brand| <= index < |brand|. Perhaps interval notation would be a bit cleaner: [-|brand|, |brand|).

At any rate, all this means is that there are valid and invalid indices. For instance, the following code snippets will result in an IndexError:

brand = "VirtualFlat"
brand[17]  # out of range
brand[-12]  # out of range

Of course, this same idea applies to any sequence type. For example, we could see this same error turn up for any of the following sequences:

nums = [1, 4, 5]
nums[7]  # IndexError: list index out of range
nums = (1, 4, 5)
nums[7]  # IndexError: tuple index out of range
nums = range(5)
nums[7]  # IndexError: range object index out of range

In the next section, we’ll take a look at this error in the context of its error message.

What Does This IndexError Message Mean?

Up to this point, we’ve talked about the IndexError broadly, but the error message we’re dealing with gives us a bit more information: IndexError: string index out of range.

Here, we can see that we’re not dealing with a list or tuple. Instead, we’re working with a string. As a result, our original example still holds:

brand = "VirtualFlat"
brand[17]  # out of range
brand[-12]  # out of range

That said, there are other ways we could get this error message to arise. For example, the Formatter class of string can throw the same error when using the get_value() method.

In fact, there are probably thousands of libraries that could throw this error, so it’s tough for me to assume your situation. As a result, in the next section, we’ll take a look at the simple case and try to come up with some general problem solving strategies.

How to Fix This IndexError?

Now that we know we have some sort of indexing issue with our string, it’s just a matter of finding the root cause.

Like the original scenario we explores, it’s possible that we have some hardcoded value that is breaching the range of our string:

brand = "VirtualFlat"
brand[17]  # out of range

In this case, we’ll probably want to generate a constant from this index and give it a good name. After all, maintaining a magic number is usually a bad idea:

brand = "VirtualFlat"
LAST_CHAR = 10
brand[LAST_CHAR]

Having solved our magic number issue, I’d argue that there’s an even better solution: we should compute the last character programatically. Of course, if we’re not careful, we could find ourselves with yet another IndexError:

brand = "VirtualFlat"
brand[len(brand)]  # out of range, again

To get the last character, we’ll need to subtract one from the length:

brand = "VirtualFlat"
brand[len(brand) - 1]

That said, if you’ve read my guide to getting the last item of a list, you know there’s an even cleaner solution. Of course, we’re not here to get the last character of a string; we’re trying to anticipate different ways in which this error could arise.

For instance, we might be doing something a bit more complicated like looping over a string:

brand = "VirtualFlat"
i = 0
while i <= len(brand):
  if i % 2 == 0:
    print(brand[i])  # sometimes out of range

Here, we’ll notice that the loop condition always takes the index one step too far. As a result, we’ll need to correct it:

brand = "VirtualFlat"
i = 0
while i < len(brand):
  if i % 2 == 0:
    print(brand[i])  # sometimes out of range

Or even better, we can take advantage of the for loop:

brand = "VirtualFlat"
for i, c in enumerate(brand):
  if i % 2 == 0:
    print(c)  # sometimes out of range

Of course, this doesn’t even begin to scratch the realm of possibility for this error. As a result, in the next section, we’ll take a look at getting you some extra help—if you need it!

Need Help Fixing This IndexError?

As someone who has been relieved of their teaching duties for a little while, I figured I’d start sharing my time with the folks of the internet. In other words, if you find this article helpful but didn’t quite give you what you needed, consider sharing your code snippet with me on Twitter.

To do that, you’re welcome to use the #RenegadePython hashtag. Typically, I use that for Python challenges, but I figured I’d open it up for general Python Q&A. Here’s a sample tweet to get you started:

At any rate, that’s all I’ve got for today. If you liked this article, I’d appreciate it if you made your way over to my list of ways to grow the site. There, you’ll find links to my newsletter, YouTube channel, and Patreon.

Likewise, here are a few related articles for your perusal:

Finally, here are a few additional Python resources on Amazon (ad):

Otherwise, thanks for stopping by and enjoy the rest of your day!

Series Navigation← SyntaxError: Expected an Indented BlockTypeError: Can’t Multiply Sequence by Non-int of Type ‘str’ →

Jeremy Grifski

Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife, playing Overwatch and Phantasy Star Online 2, practicing trombone, watching Penguins hockey, and traveling the world.

Recent Content