gchq/CyberChef · error · OperationError
Plugboard wiring must be 26 unique uppercase letters
Error message
Plugboard wiring must be 26 unique uppercase letters
What it means
Thrown by the Typex Plugboard constructor in Typex.mjs when the `wiring` string fails the regex /^[A-Z]{26}$/. The plugboard wiring must be exactly 26 uppercase ASCII letters (a permutation of the alphabet) because the constructor mirrors it through the reversed alphabet and passes it to the Enigma Rotor superclass. The regex checks length and character set but not uniqueness — uniqueness is enforced later by the superclass, whose error is rewritten at line 204.
Source
Thrown at src/core/lib/Typex.mjs:195
* it means everything else continues to work like in the Enigma.
*/
export class Plugboard extends Enigma.Rotor {
/**
* Typex plugboard constructor.
*
* @param {string} wiring - 26 character string of mappings from A-Z, as per rotors, or "".
*/
constructor(wiring) {
// Typex input wiring is backwards vs Enigma: that is, letters enter the rotors in a
// clockwise order, vs. Enigma's anticlockwise (or vice versa depending on which side
// you're looking at it from). I'm doing the transform here to avoid having to rewrite
// the Engima crypt() method in Typex as well.
// Note that the wiring for the reflector is the same way around as Enigma, so no
// transformation is necessary on that side.
// We're going to achieve this by mapping the plugboard settings through an additional
// transform that mirrors the alphabet before we pass it to the superclass.
if (!/^[A-Z]{26}$/.test(wiring)) {
throw new OperationError("Plugboard wiring must be 26 unique uppercase letters");
}
const reversed = "AZYXWVUTSRQPONMLKJIHGFEDCB";
wiring = wiring.replace(/./g, x => {
return reversed[Enigma.a2i(x)];
});
try {
super(wiring, "", "A", "A");
} catch (err) {
throw new OperationError(err.message.replace("Rotor", "Plugboard"));
}
}
/**
* Transform a character through this rotor forwards.
*
* @param {number} c - The character.
* @returns {number}
*/View on GitHub (pinned to 4290ea7539)
Solutions
- Pass a 26-character string of uppercase A-Z representing the alphabet permutation, e.g. the identity "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
- To express an empty/identity plugboard, pass the identity alphabet string (the constructor does not accept "" for no plugboard — it requires 26 letters).
- Validate wiring with /^[A-Z]{26}$/.test(wiring) and (separately) that all 26 letters are unique before constructing.
Example fix
// before
new Plugboard("ABCDE...24 chars"); // too short
// after
new Plugboard("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); Defensive patterns
Strategy: validation
Validate before calling
function isValidPlugboardWiring(w) {
return typeof w === "string" && /^[A-Z]{26}$/.test(w);
}
if (!isValidPlugboardWiring(wiring)) {
throw new Error(
`Plugboard wiring must be exactly 26 uppercase letters (A-Z). Got: '${wiring}' (len ${wiring?.length}).`
);
}
new Typex.Plugboard(wiring); Type guard
function isValidPlugboardWiring(w) {
return typeof w === "string" && /^[A-Z]{26}$/.test(w);
} Try / catch
try {
plugboard = new Typex.Plugboard(wiring);
} catch (e) {
if (e instanceof OperationError && /Plugboard wiring must be 26/.test(e.message)) {
return { error: `Plugboard wiring must be 26 uppercase letters. Use the identity alphabet for no swapping.` };
}
throw e;
} Prevention
- For a pass-through plugboard, pass the identity "ABCDEFGHIJKLMNOPQRSTUVWXYZ" — the constructor does not accept empty string.
- Do not reuse Enigma plugboard pair strings (e.g. "AB CD") — Typex expects a full 26-letter permutation.
- Validate wiring format at the UI/config boundary so the error is caught before cipher construction.
When it happens
Trigger: Constructing `new Typex.Plugboard(wiring)` with a string that is not exactly 26 uppercase letters: wrong length (25/27 chars), lowercase letters, digits, punctuation, an empty string passed where a wiring was expected, or a wiring built by string concatenation with stray characters.
Common situations: User-typed wiring in a UI; config file with a typo; reusing an Enigma plugboard string (which has a different format, pairs like "AB CD"); trimming the string inconsistently.
Related errors
- err.message.replace("Rotor", "Plugboard")
- Typex must have 5 rotors
- Invalid block cipher mode: ${mode}
- Invalid ciphertext length: ${originalLength} bytes. Must be
- No padding requested but input is not a ${blockSize}-byte mu
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/5ed22dea932effca.
Report an issue: GitHub.