TheAlgorithms/Python · error · ValueError

plain must contain only lowercase letters (a-z)

Error message

plain must contain only lowercase letters (a-z)

What it means

Raised by a1z26 encode() when the plaintext contains anything besides lowercase letters — uppercase letters, digits, punctuation, or spaces all fail. The check `not plain.islower() or not plain.isalpha()` requires the string to be entirely a-z, because the cipher maps each character via ord(elem) - 96 to its alphabet position (a=1..z=26).

Source

Thrown at ciphers/a1z26.py:30

def encode(plain: str) -> list[int]:
    """
    >>> encode("myname")
    [13, 25, 14, 1, 13, 5]
    >>> encode("abCd")
    Traceback (most recent call last):
        ...
    ValueError: plain must contain only lowercase letters (a-z)
    >>> encode("n0w")
    Traceback (most recent call last):
        ...
    ValueError: plain must contain only lowercase letters (a-z)
    >>> encode("later!")
    Traceback (most recent call last):
        ...
    ValueError: plain must contain only lowercase letters (a-z)
    """
    if not plain.islower() or not plain.isalpha():
        raise ValueError("plain must contain only lowercase letters (a-z)")
    return [ord(elem) - 96 for elem in plain]


def decode(encoded: list[int]) -> str:
    """
    >>> decode([13, 25, 14, 1, 13, 5])
    'myname'
    """
    return "".join(chr(elem + 96) for elem in encoded)


def main() -> None:
    encoded = encode(input("-> ").strip().lower())
    print("Encoded: ", encoded)
    print("Decoded:", decode(encoded))


if __name__ == "__main__":

View on GitHub (pinned to f5988cc097)

Solutions

  1. Normalize input first: plain = plain.lower() and strip non-letters, e.g. ''.join(c for c in text.lower() if c.isalpha()).
  2. If spaces must be preserved, use a different cipher from the repo or extend encode() yourself.
  3. Reject early with a clear message in your own input pipeline rather than relying on the traceback.

Example fix

# before
encode('later!')  # ValueError: plain must contain only lowercase letters (a-z)

# after
encode(''.join(c for c in 'later!'.lower() if c.isalpha()))  # [12,1,20,5,18]
Defensive patterns

Strategy: validation

Validate before calling

plain = ''.join(c for c in text.lower() if c.isalpha())
if not plain:
    raise ValueError('no letters to encode')

Type guard

def is_all_lowercase_alpha(s: str) -> bool:
    return s.isalpha() and s.islower()

Try / catch

try:
    encode(plain)
except ValueError as e:
    if 'lowercase' in str(e):
        plain = ''.join(c for c in plain.lower() if c.isalpha())
        encode(plain)

Prevention

When it happens

Trigger: Calling encode('Hello'), encode('n0w'), or encode('later!') as in the doctests. Any space also fails, since isalpha() is False for spaces.

Common situations: Feeding raw user sentences (capitalized or with punctuation) without preprocessing, or assuming the cipher handles spaces like other classical ciphers in the repo do.

Related errors


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