TheAlgorithms/Python · error · KeyError

invalid input option

Error message

invalid input option

What it means

Raised by main() in ciphers/simple_keyword_cypher.py when the option prompt answer's first character is not 'e' or 'd'. The lookup dict {'e': encipher, 'd': decipher} raises KeyError, which is re-raised with the message 'invalid input option'. Note: input(...)[0] will IndexError first on an empty line.

Source

Thrown at ciphers/simple_keyword_cypher.py:89

    """
    # Reverse our cipher mappings
    rev_cipher_map = {v: k for k, v in cipher_map.items()}
    return "".join(rev_cipher_map.get(ch, ch) for ch in message.upper())


def main() -> None:
    """
    Handles I/O

    :return: void
    """
    message = input("Enter message to encode or decode: ").strip()
    key = input("Enter keyword: ").strip()
    option = input("Encipher or decipher? E/D:").strip()[0].lower()
    try:
        func = {"e": encipher, "d": decipher}[option]
    except KeyError:
        raise KeyError("invalid input option")
    cipher_map = create_cipher_map(key)
    print(func(message, cipher_map))


if __name__ == "__main__":
    import doctest

    doctest.testmod()
    main()

View on GitHub (pinned to f5988cc097)

Solutions

  1. Answer with a string starting with 'e' (encipher) or 'd' (decipher), e.g. 'encipher'
  2. Re-prompt on bad input instead of crashing: loop until option[0] in {'e', 'd'}
  3. For automation, call encipher/decipher directly instead of driving the interactive main()

Example fix

# before (main loop)
option = input("Encipher or decipher? E/D:").strip()[0].lower()
try:
    func = {"e": encipher, "d": decipher}[option]
except KeyError:
    raise KeyError("invalid input option")

# after
while True:
    option = input("Encipher or decipher? E/D:").strip().lower()
    if option and option[0] in {"e", "d"}:
        func = {"e": encipher, "d": decipher}[option[0]]
        break
    print("Please answer 'e' or 'd'.")
Defensive patterns

Strategy: validation

Validate before calling

option = input('Encipher or decipher? E/D:').strip().lower()
while not option or option[0] not in {'e', 'd'}:
    option = input("Please answer 'e' or 'd':").strip().lower()
func = {'e': encipher, 'd': decipher}[option[0]]

Type guard

def valid_option(answer: str) -> bool:
    return bool(answer) and answer.strip().lower()[0] in {'e', 'd'}

Try / catch

try:
    func = {'e': encipher, 'd': decipher}[option]
except KeyError:
    print("invalid input option; please answer 'e' or 'd'")
    option = input('Encipher or decipher? E/D:').strip().lower()[0]
    func = {'e': encipher, 'd': decipher}[option]

Prevention

When it happens

Trigger: Answering 'x', 'encode', 'E ' is fine but 'encode' works ('e' taken); answering 'q' or 'help'; pressing Enter on an empty line (raises IndexError before the KeyError); answering uppercase is fine due to .lower().

Common situations: Interactive CLI users typing full words is OK ('encode' -> 'e') but invalid choices like 'both' or 'n' fail; piping empty input into the script; non-interactive automation calling the script without a TTY.

Related errors


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