{"record":{"id":"c0f8de3d1f0196c1","repo":"gchq/CyberChef","slug":"no-key-entered","errorCode":null,"errorMessage":"No key entered","messagePattern":"No key entered","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/VigenèreDecode.mjs","lineNumber":49,"sourceCode":"            }\n        ];\n    }\n\n    /**\n     * @param {string} input\n     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        const alphabet = \"abcdefghijklmnopqrstuvwxyz\",\n            key = args[0].toLowerCase();\n        let output = \"\",\n            fail = 0,\n            keyIndex,\n            msgIndex,\n            chr;\n\n        if (!key) throw new OperationError(\"No key entered\");\n        if (!/^[a-zA-Z]+$/.test(key)) throw new OperationError(\"The key must consist only of letters\");\n\n        for (let i = 0; i < input.length; i++) {\n            if (alphabet.indexOf(input[i]) >= 0) {\n                chr = key[(i - fail) % key.length];\n                keyIndex = alphabet.indexOf(chr);\n                msgIndex = alphabet.indexOf(input[i]);\n                // Subtract indexes from each other, add 26 just in case the value is negative,\n                // modulo to remove if necessary\n                output += alphabet[(msgIndex - keyIndex + alphabet.length) % 26];\n            } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {\n                chr = key[(i - fail) % key.length].toLowerCase();\n                keyIndex = alphabet.indexOf(chr);\n                msgIndex = alphabet.indexOf(input[i].toLowerCase());\n                output += alphabet[(msgIndex + alphabet.length - keyIndex) % 26].toUpperCase();\n            } else {\n                output += input[i];\n                fail++;","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/VigenèreDecode.mjs#L31-L67","documentation":"Thrown by 'Vigenere Decode' when the key argument (args[0]) lowercased is the empty string. A Vigenere cipher requires a non-empty alphabetic key to determine the shift per character; an empty key would cause division-by-zero in the modular key indexing.","triggerScenarios":"Leaving the key field empty, passing an empty string, or loading a recipe where the key was not saved. The empty-key check precedes the letters-only check.","commonSituations":"User clears the key field, or a recipe is shared/imported without the key value.","solutions":["Enter a non-empty key consisting only of letters (a-z, A-Z).","Check imported recipe JSON for a missing/blank key field.","If you do not know the key, brute-force/analyse the ciphertext rather than leaving the key blank."],"exampleFix":"// before\nvigenereDecode(ciphertext, \"\");\n// after\nvigenereDecode(ciphertext, \"LEMON\");","handlingStrategy":"validation","validationCode":"const key = String(args[0] ?? \"\").toLowerCase();\nif (key === \"\") throw new Error(\"Vigenere key must not be empty\");\nif (!/^[a-z]+$/.test(key)) throw new Error(\"Vigenere key must be letters only\");","typeGuard":"function isValidVigenereKey(k) { const s = String(k ?? \"\").toLowerCase(); return s !== \"\" && /^[a-z]+$/.test(s); }","tryCatchPattern":null,"preventionTips":["Default recipes to a placeholder key rather than blank.","Validate imported recipes for empty key fields."],"tags":["cipher","vigenere","validation","argument-error"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}