gchq/CyberChef · error · OperationError

connects more than once

Error message

${name} connects ${pair[0]} more than once

What it means

Thrown by the PairMapBase constructor when a letter appears in more than one pair — the map already has an entry for that letter. Each letter may be connected to at most one partner (self-stecker pairs like 'AA' are silently ignored). The error interpolates name (e.g. 'Plugboard' or 'Reflector') and the offending letter.

Solutions

  1. Ensure each letter appears in at most one pair across the whole spec.
  2. Before constructing, build a usage map and reject any letter seen twice.
  3. Deduplicate pairs and remove conflicting entries.

Example fix

// before
new Plugboard('AY AB CD'); // A connected to Y and B

// after
new Plugboard('AY BC DE'); // each letter unique
Defensive patterns

Strategy: validation

Validate before calling

function hasNoDoubleConnect(pairs) {
  const seen = new Set();
  for (const tok of pairs.split(/\s+/).filter(Boolean)) {
    const [a, b] = [tok[0], tok[1]];
    if (a === b) continue; // self-stecker allowed
    if (seen.has(a) || seen.has(b)) return false;
    seen.add(a); seen.add(b);
  }
  return true;
}
if (!hasNoDoubleConnect(pairs)) {
  throw new Error("Each letter may appear in at most one pair.");
}

Type guard

function isNonOverlappingPairs(pairs) {
  const seen = new Set();
  for (const tok of pairs.split(/\s+/).filter(Boolean)) {
    const [a, b] = [tok[0], tok[1]];
    if (a === b) continue;
    if (seen.has(a) || seen.has(b)) return false;
    seen.add(a); seen.add(b);
  }
  return true;
}

Prevention

When it happens

Trigger: new Plugboard('AY AB ...') or new Reflector(...) where 'A' is connected to both Y and B — the second pair triggers hasOwnProperty(map, a) and throws. Same for the partner letter (the b-side check covers reversed overlaps).

Common situations: Listing a plugboard connection twice for the same letter; copying a reflector spec that double-binds a letter; editing a pair and forgetting to remove the old one; overlapping pairs from merge errors.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/fdbc678556daa81b. Report an issue: GitHub.

Appendix: source

Thrown at src/core/lib/Enigma.mjs:188

    constructor(pairs, name="PairMapBase") {
        // I've chosen to make whitespace significant here to make a) code and
        // b) inputs easier to read
        this.pairs = pairs;
        this.map = {};
        if (pairs === "") {
            return;
        }
        pairs.split(/\s+/).forEach(pair => {
            if (!/^[A-Z]{2}$/.test(pair)) {
                throw new OperationError(name + " must be a whitespace-separated list of uppercase letter pairs");
            }
            const a = a2i(pair[0]), b = a2i(pair[1]);
            if (a === b) {
                // self-stecker
                return;
            }
            if (Object.prototype.hasOwnProperty.call(this.map, a)) {
                throw new OperationError(`${name} connects ${pair[0]} more than once`);
            }
            if (Object.prototype.hasOwnProperty.call(this.map, b)) {
                throw new OperationError(`${name} connects ${pair[1]} more than once`);
            }
            this.map[a] = b;
            this.map[b] = a;
        });
    }

    /**
     * Transform a character through this object.
     * Returns other characters unchanged.
     *
     * @param {number} c - The character.
     * @returns {number}
     */
    transform(c) {
        if (!Object.prototype.hasOwnProperty.call(this.map, c)) {

View on GitHub (pinned to 4290ea7539)