{"record":{"id":"283f421016179f85","repo":"gchq/CyberChef","slug":"no-key-entered-283f42","errorCode":null,"errorMessage":"No key entered","messagePattern":"No key entered","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/VigenèreEncode.mjs","lineNumber":50,"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                // Get the corresponding character of key for the current letter, accounting\n                // for chars not in alphabet\n                chr = key[(i - fail) % key.length];\n                // Get the location in the vigenere square of the key char\n                keyIndex = alphabet.indexOf(chr);\n                // Get the location in the vigenere square of the message char\n                msgIndex = alphabet.indexOf(input[i]);\n                // Get the encoded letter by finding the sum of indexes modulo 26 and finding\n                // the letter corresponding to that\n                output += alphabet[(keyIndex + msgIndex) % 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());","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/VigenèreEncode.mjs#L32-L68","documentation":"Thrown by 'Vigenere Encode' when the key argument (args[0]) lowercased is the empty string. Same rationale as decode: the per-character shift needs a non-empty alphabetic key, and an empty key would break the modular indexing into key.length.","triggerScenarios":"Empty key field, empty string passed programmatically, or a recipe with a blank key. The empty check runs before the letters-only validation.","commonSituations":"Cleared key field, imported recipe missing the key, or building a recipe programmatically and forgetting to set the key.","solutions":["Provide a non-empty, letters-only key.","Verify recipe JSON carries a non-empty key value.","Generate a random alphabetic key if one is needed rather than leaving blank."],"exampleFix":"// before\nvigenereEncode(plaintext, \"\");\n// after\nvigenereEncode(plaintext, \"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":["Generate a random alphabetic key rather than leaving blank.","Check shared recipes for missing key values."],"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"}