donnemartin/interactive-coding-challenges · error · KeyError

word does not exist

Error message

word does not exist

What it means

Raised by Trie.remove when the word is not stored as a terminated word in the trie. find returns a node only if the full path exists AND the final node has terminates=True; otherwise remove raises KeyError. Prefixes of stored words also trigger this (e.g. removing 'ab' when only 'abc' is stored).

Solutions

  1. Check with trie.find(word) first and only remove if it returns a node
  2. Track deletion state upstream to avoid double-remove
  3. Catch KeyError and treat 'already absent' as success (idempotent delete)

Example fix

# before
trie.remove(word)  # KeyError if absent

# after
if trie.find(word) is not None:
    trie.remove(word)
Defensive patterns

Strategy: try-catch

Validate before calling

if trie.find(word) is not None:
    trie.remove(word)

Type guard

def word_in_trie(trie, word) -> bool:
    return word is not None and trie.find(word) is not None

Try / catch

try:
    trie.remove(word)
except KeyError:
    pass  # word already absent

Prevention

When it happens

Trigger: Calling remove on a never-inserted word; removing a word twice; removing a proper prefix of a stored word.

Common situations: Duplicate delete requests in request handling; deleting from stale word lists; assuming prefixes count as words.

Related errors


AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28). Data as JSON: /api/errors/a66272f1c566a40b. Report an issue: GitHub.

Appendix: source

Thrown at graphs_trees/trie/trie.py:47

    def insert(self, word):
        if word is None:
            raise TypeError('word cannot be None')
        node = self.root
        parent = None
        for char in word:
            if char in node.children:
                node = node.children[char]
            else:
                node.children[char] = Node(char, parent=node)
                node = node.children[char]
        node.terminates = True

    def remove(self, word):
        if word is None:
            raise TypeError('word cannot be None')
        node = self.find(word)
        if node is None:
            raise KeyError('word does not exist')
        node.terminates = False
        parent = node.parent
        while parent is not None:
            # As we are propagating the delete up the 
            # parents, if this node has children, stop
            # here to prevent orphaning its children.
            # Or
            # if this node is a terminating node that is
            # not the terminating node of the input word, 
            # stop to prevent removing the associated word.
            if node.children or node.terminates:
                return
            del parent.children[node.key]
            node = parent
            parent = parent.parent

    def list_words(self):
        result = []

View on GitHub (pinned to 358f2cc604)