TheAlgorithms/Python · error · ValueError

First rotor position is not within range of 1..26 ({rotorpos

Error message

First rotor position is not within range of 1..26 ({rotorpos1}

What it means

Raised by the Enigma machine validator when the FIRST rotor position is outside 1..26 (len(abc)). Rotor positions are 1-based in this API, so 0, negatives, and anything above 26 fail. Minor cosmetic bug: the f-string message is missing its closing parenthesis.

Source

Thrown at ciphers/enigma_machine2.py:100

'ZJXESIUQLHAVRMDOYGTNFWPBKC'), \
{'P': 'O', 'O': 'P', 'L': 'A', 'A': 'L', 'N': 'D', 'D': 'N'})

    :param rotpos: rotor_positon
    :param rotsel: rotor_selection
    :param pb: plugb -> validated and transformed
    :return: (`rotpos`, `rotsel`, `pb`)
    """
    # Checks if there are 3 unique rotors

    if (unique_rotsel := len(set(rotsel))) < 3:
        msg = f"Please use 3 unique rotors (not {unique_rotsel})"
        raise Exception(msg)

    # Checks if rotor positions are valid
    rotorpos1, rotorpos2, rotorpos3 = rotpos
    if not 0 < rotorpos1 <= len(abc):
        msg = f"First rotor position is not within range of 1..26 ({rotorpos1}"
        raise ValueError(msg)
    if not 0 < rotorpos2 <= len(abc):
        msg = f"Second rotor position is not within range of 1..26 ({rotorpos2})"
        raise ValueError(msg)
    if not 0 < rotorpos3 <= len(abc):
        msg = f"Third rotor position is not within range of 1..26 ({rotorpos3})"
        raise ValueError(msg)

    # Validates string and returns dict
    pbdict = _plugboard(pb)

    return rotpos, rotsel, pbdict


def _plugboard(pbstring: str) -> dict[str, str]:
    """
    https://en.wikipedia.org/wiki/Enigma_machine#Plugboard

    >>> _plugboard('PICTURES')

View on GitHub (pinned to f5988cc097)

Solutions

  1. Use positions in 1..26 inclusive, e.g. rotpos=(1, 1, 1)
  2. Clamp/convert 0-based values: rotpos = tuple(p + 1 for p in zero_based)
  3. Validate all three positions with all(0 < p <= 26 for p in rotpos) before the call

Example fix

# before
rotpos = (0, 13, 26)  # first rotor invalid

# after
rotpos = (1, 13, 26)
Defensive patterns

Strategy: validation

Validate before calling

rotpos1, rotpos2, rotpos3 = rotpos
assert 0 < rotpos1 <= 26, "rotor positions are 1-based, 1..26"

Type guard

def valid_rotor_positions(rotpos) -> bool:
    return len(rotpos) == 3 and all(0 < p <= 26 for p in rotpos)

Try / catch

try:
    settings = validate_and_transform(rotpos, rotsel, pb)
except ValueError as exc:
    if "rotor position" in str(exc):
        rotpos = tuple(min(max(p, 1), 26) for p in rotpos)
    else:
        raise

Prevention

When it happens

Trigger: Calling with rotpos=(0, 1, 1), (-3, 5, 5), or (27, 1, 1); converting 0-based positions from another API without adding 1.

Common situations: Index math off-by-one after porting code that used 0-based rotor settings; parsing user input without range checking; random.randint(0, 26) instead of randint(1, 26).

Related errors


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