TheAlgorithms/Python · error · Exception
Please use 3 unique rotors (not {unique_rotsel})
Error message
Please use 3 unique rotors (not {unique_rotsel}) What it means
Raised by the Enigma machine's input validator (ciphers/enigma_machine2.py) when fewer than 3 unique rotors are selected: len(set(rotsel)) < 3. The historical machine needs three distinct physical rotors, so duplicates (e.g. [1, 2, 2] or [5, 5, 5]) are rejected. Note it raises bare Exception, not a more specific type.
Source
Thrown at ciphers/enigma_machine2.py:94
) -> tuple[RotorPositionT, RotorSelectionT, dict[str, str]]:
"""
Checks if the values can be used for the ``enigma`` function
>>> _validator((1,1,1), (rotor1, rotor2, rotor3), 'POLAND')
((1, 1, 1), ('EGZWVONAHDCLFQMSIPJBYUKXTR', 'FOBHMDKEXQNRAULPGSJVTYICZW', \
'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
View on GitHub (pinned to f5988cc097)
Solutions
- Pass three distinct rotor selectors, e.g. rotsel=(1, 2, 3)
- If generating randomly, use random.sample(range(1, 6), 3) (without replacement)
- Check len(set(rotsel)) == 3 before calling the API
Example fix
# before rotsel = (1, 2, 2) enigma(rotpos, rotsel, pb) # after import random rotsel = tuple(random.sample(range(1, 6), 3)) # 3 distinct rotors enigma(rotpos, rotsel, pb)
Defensive patterns
Strategy: validation
Validate before calling
if len(set(rotsel)) < 3:
raise ValueError("select 3 distinct rotors") Type guard
def valid_rotor_selection(rotsel) -> bool:
return len(set(rotsel)) == 3 Try / catch
try:
settings = validate_and_transform(rotpos, rotsel, pb)
except Exception as exc: # module raises bare Exception here
if "unique rotors" in str(exc):
rotsel = (1, 2, 3) # fall back to distinct defaults
else:
raise Prevention
- Always pass three distinct rotor ids
- Use random.sample(range(1, 6), 3) for random selection
- Check len(set(rotsel)) == 3 in your settings loader
When it happens
Trigger: Calling enigma with rotsel like (1, 2, 2), (3, 3, 3), or any tuple with duplicate rotor ids; passing strings vs ints inconsistently so set() collapses them ('1', 1) is not the issue here but duplicates are.
Common situations: Random rotor selection code that samples with replacement; UI defaults that repeat rotor I; refactoring from a 2-rotor toy example to the 3-rotor API.
Related errors
- First rotor position is not within range of 1..26 ({rotorpos
- Second rotor position is not within range of 1..26 ({rotorpo
- Third rotor position is not within range of 1..26 ({rotorpos
- Plugboard setting isn't type string ({type(pbstring)})
- Odd number of symbols ({len(pbstring)})
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/c1c28a84833b3a06.
Report an issue: GitHub.