TheAlgorithms/Python · error · IndexError

list index out of range.

Error message

list index out of range.

What it means

Raised by CircularLinkedList.insert_nth(index, data) when index < 0 or index > len(self) — the valid insertion window is 0..length inclusive (index == length appends). It raises IndexError (not ValueError) with message 'list index out of range.', deliberately mirroring CPython list.insert-adjacent error semantics. Because the list is circular, insertion at 0 relinks tail.next_node rather than a head pointer alone.

Source

Thrown at data_structures/linked_list/circular_linked_list.py:69

    def insert_head(self, data: Any) -> None:
        """
        Insert a node with the given data at the beginning of the Circular Linked List.
        """
        self.insert_nth(0, data)

    def insert_nth(self, index: int, data: Any) -> None:
        """
        Insert the data of the node at the nth pos in the Circular Linked List.
        Args:
            index: The index at which the data should be inserted.
            data: The data to be inserted.

        Raises:
            IndexError: If the index is out of range.
        """
        if index < 0 or index > len(self):
            raise IndexError("list index out of range.")
        new_node: Node = Node(data)
        if self.head is None:
            new_node.next_node = new_node  # First node points to itself
            self.tail = self.head = new_node
        elif index == 0:  # Insert at the head
            new_node.next_node = self.head
            assert self.tail is not None  # List is not empty, tail exists
            self.head = self.tail.next_node = new_node
        else:
            temp: Node | None = self.head
            for _ in range(index - 1):
                assert temp is not None
                temp = temp.next_node
            assert temp is not None
            new_node.next_node = temp.next_node
            temp.next_node = new_node
            if index == len(self) - 1:  # Insert at the tail
                self.tail = new_node

View on GitHub (pinned to f5988cc097)

Solutions

  1. Validate before calling: `if 0 <= index <= len(cll): cll.insert_nth(index, data)`
  2. Convert 1-based user input: index = user_pos - 1, then bounds-check
  3. Recompute len(cll) at call time instead of caching it

Example fix

# before
cll.insert_nth(len(cll) + 5, 'x')  # IndexError

# after
index = min(index, len(cll))
index = max(index, 0)
cll.insert_nth(index, 'x')
Defensive patterns

Strategy: validation

Validate before calling

if not 0 <= index <= len(cll):
    raise IndexError(f'index {index} outside 0..{len(cll)}')
cll.insert_nth(index, data)

Type guard

def is_valid_nth(cll, index: object) -> bool:
    return isinstance(index, int) and 0 <= index <= len(cll)

Try / catch

try:
    cll.insert_nth(index, data)
except IndexError:
    cll.insert_nth(len(cll), data)  # append on out-of-range

Prevention

When it happens

Trigger: cll.insert_nth(-1, x); cll.insert_nth(len(cll) + 1, x) on a list of known length; insert_nth called on a list whose length shrank after prior deletions while the caller cached the old length.

Common situations: Index math derived from enumerate offsets that go negative; UI-driven insert-at-position with 1-based input passed through unconverted; cached length going stale.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/0dda308324bd83d3. Report an issue: GitHub.