TheAlgorithms/Python · error · KeyError

Length of alphabet has to be 27.

Error message

Length of alphabet has to be 27.

What it means

Raised by trifid_cipher's internal __prepare helper when the supplied alphabet does not contain exactly 27 characters after spaces are stripped and it is uppercased. The trifid cipher needs a 27-symbol alphabet: the 26 letters A-Z plus one extra symbol (the default is '.'). It is raised as a KeyError, which is unusual for input validation but matches the module's existing convention.

Source

Thrown at ciphers/trifid_cipher.py:111

    >>> __prepare('am i a boy?','abCdeFghijkLmnopqrStuVwxYZ+')
    Traceback (most recent call last):
        ...
    ValueError: Each message character has to be included in alphabet!

    Testing with numbers

    >>> __prepare(500,'abCdeFghijkLmnopqrStuVwxYZ+')
    Traceback (most recent call last):
        ...
    AttributeError: 'int' object has no attribute 'replace'
    """
    # Validate message and alphabet, set to upper and remove spaces
    alphabet = alphabet.replace(" ", "").upper()
    message = message.replace(" ", "").upper()

    # Check length and characters
    if len(alphabet) != 27:
        raise KeyError("Length of alphabet has to be 27.")
    if any(char not in alphabet for char in message):
        raise ValueError("Each message character has to be included in alphabet!")

    # Generate dictionares
    character_to_number = dict(zip(alphabet, TEST_CHARACTER_TO_NUMBER.values()))
    number_to_character = {
        number: letter for letter, number in character_to_number.items()
    }

    return message, alphabet, character_to_number, number_to_character


def encrypt_message(
    message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5
) -> str:
    """
    encrypt_message
    ===============

View on GitHub (pinned to f5988cc097)

Solutions

  1. Use the default alphabet by omitting the argument: encrypt_message(message)
  2. Or pass exactly 27 unique uppercase characters, e.g. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.'
  3. If building alphabets dynamically, assert len(set(alphabet)) == 27 before calling
  4. Note the alphabet must be a str; passing an int causes AttributeError ('int' object has no attribute 'replace') before this check runs

Example fix

# before
encrypt_message('HELP', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
# KeyError: Length of alphabet has to be 27.

# after
encrypt_message('HELP', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.')
Defensive patterns

Strategy: validation

Validate before calling

def valid_trifid_alphabet(alphabet: str) -> bool:
    a = alphabet.replace(' ', '').upper()
    return len(a) == 27 and len(set(a)) == 27

Type guard

def is_trifid_alphabet(v) -> bool:
    return isinstance(v, str) and len(v.replace(' ', '')) == 27

Try / catch

try:
    encrypt_message(msg, alphabet)
except KeyError as e:
    if 'Length of alphabet' in str(e):
        raise ValueError('trifid alphabet must be 27 unique characters') from e
    raise

Prevention

When it happens

Trigger: Calling encrypt_message/decrypt_message with alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ' (26 chars, missing the 27th symbol), or with a 27+ char alphabet containing duplicates/spaces that still leaves the length wrong after normalization, e.g. encrypt_message('HELP', 'ABC.') or __prepare('MSG', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.+').

Common situations: Copy-pasting a plain 26-letter alphabet from another cipher (Caesar, Playfair) into the trifid API; forgetting the trailing '.' separator; assuming the alphabet param is optional padding-tolerant like in other cipher modules.

Related errors


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