{"record":{"id":"fdbc678556daa81b","repo":"gchq/CyberChef","slug":"name-connects-pair-0-more-than-once","errorCode":null,"errorMessage":"${name} connects ${pair[0]} more than once","messagePattern":"(.+?) connects (.+?) more than once","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Enigma.mjs","lineNumber":188,"sourceCode":"    constructor(pairs, name=\"PairMapBase\") {\n        // I've chosen to make whitespace significant here to make a) code and\n        // b) inputs easier to read\n        this.pairs = pairs;\n        this.map = {};\n        if (pairs === \"\") {\n            return;\n        }\n        pairs.split(/\\s+/).forEach(pair => {\n            if (!/^[A-Z]{2}$/.test(pair)) {\n                throw new OperationError(name + \" must be a whitespace-separated list of uppercase letter pairs\");\n            }\n            const a = a2i(pair[0]), b = a2i(pair[1]);\n            if (a === b) {\n                // self-stecker\n                return;\n            }\n            if (Object.prototype.hasOwnProperty.call(this.map, a)) {\n                throw new OperationError(`${name} connects ${pair[0]} more than once`);\n            }\n            if (Object.prototype.hasOwnProperty.call(this.map, b)) {\n                throw new OperationError(`${name} connects ${pair[1]} more than once`);\n            }\n            this.map[a] = b;\n            this.map[b] = a;\n        });\n    }\n\n    /**\n     * Transform a character through this object.\n     * Returns other characters unchanged.\n     *\n     * @param {number} c - The character.\n     * @returns {number}\n     */\n    transform(c) {\n        if (!Object.prototype.hasOwnProperty.call(this.map, c)) {","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Enigma.mjs#L170-L206","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure each letter appears in at most one pair across the whole spec.","Before constructing, build a usage map and reject any letter seen twice.","Deduplicate pairs and remove conflicting entries."],"exampleFix":"// before\nnew Plugboard('AY AB CD'); // A connected to Y and B\n\n// after\nnew Plugboard('AY BC DE'); // each letter unique","handlingStrategy":"validation","validationCode":"function hasNoDoubleConnect(pairs) {\n  const seen = new Set();\n  for (const tok of pairs.split(/\\s+/).filter(Boolean)) {\n    const [a, b] = [tok[0], tok[1]];\n    if (a === b) continue; // self-stecker allowed\n    if (seen.has(a) || seen.has(b)) return false;\n    seen.add(a); seen.add(b);\n  }\n  return true;\n}\nif (!hasNoDoubleConnect(pairs)) {\n  throw new Error(\"Each letter may appear in at most one pair.\");\n}","typeGuard":"function isNonOverlappingPairs(pairs) {\n  const seen = new Set();\n  for (const tok of pairs.split(/\\s+/).filter(Boolean)) {\n    const [a, b] = [tok[0], tok[1]];\n    if (a === b) continue;\n    if (seen.has(a) || seen.has(b)) return false;\n    seen.add(a); seen.add(b);\n  }\n  return true;\n}","tryCatchPattern":null,"preventionTips":["Track each letter's usage; reject specs binding a letter twice.","Deduplicate and resolve conflicts before constructing.","Remember a Reflector additionally needs all 13 pairs covering every letter."],"tags":["enigma","cryptography","input-validation","plugboard","reflector","duplicate"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}