{"record":{"id":"b191c7ce6bfa8036","repo":"gchq/CyberChef","slug":"crib-cannot-be-empty-b191c7","errorCode":null,"errorMessage":"Crib cannot be empty","messagePattern":"Crib cannot be empty","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/MultipleBombe.mjs","lineNumber":217,"sourceCode":"        }\n        if (fourthRotorsStr !== \"\") {\n            for (let rstr of fourthRotorsStr.split(\"\\n\")) {\n                rstr = this.validateRotor(rstr);\n                fourthRotors.push(rstr);\n            }\n        }\n        if (fourthRotors.length === 0) {\n            fourthRotors.push(\"\");\n        }\n        for (const rstr of reflectorsStr.split(\"\\n\")) {\n            const reflector = new Reflector(rstr);\n            reflectors.push(reflector);\n        }\n        if (reflectors.length === 0) {\n            throw new OperationError(\"A minimum of one reflector must be supplied\");\n        }\n        if (crib.length === 0) {\n            throw new OperationError(\"Crib cannot be empty\");\n        }\n        if (offset < 0) {\n            throw new OperationError(\"Offset cannot be negative\");\n        }\n        // For symmetry with the Enigma op, for the input we'll just remove all invalid characters\n        input = input.replace(/[^A-Za-z]/g, \"\").toUpperCase();\n        crib = crib.replace(/[^A-Za-z]/g, \"\").toUpperCase();\n        const ciphertext = input.slice(offset);\n        let update;\n        if (isWorkerEnvironment()) {\n            update = this.updateStatus;\n        } else {\n            update = undefined;\n        }\n        let bombe = undefined;\n        const output = {bombeRuns: []};\n        // I could use a proper combinatorics algorithm here... but it would be more code to\n        // write one, and we don't seem to have one in our existing libraries, so massively nested","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/MultipleBombe.mjs#L199-L235","documentation":"Thrown by MultipleBombe.run when the crib (args[4]) is an empty string. The Bombe attack requires a known plaintext fragment (the 'crib') to build its menu; without one there is nothing to test rotor settings against.","triggerScenarios":"run(input, args) where args[4] === '' (the Crib field). Checked before the crib is uppercased/filtered, so any zero-length string trips it.","commonSituations":"User forgot to enter a crib; crib was in a different field; recipe loaded with the crib field blanked; crib consisted only of characters that were intended but never typed.","solutions":["Enter a known-plaintext fragment in the Crib field (e.g. 'WETTER').","Ensure the crib actually appears in the ciphertext at the given offset.","Double-check the crib is not just whitespace — although note the check uses raw length, so whitespace passes but will be stripped later leaving an empty effective crib."],"exampleFix":"// before\nchef.bake(\"Multiple Bombe\", [..., \"\", 0, true]);\n// after\nchef.bake(\"Multiple Bombe\", [..., \"WETTER\", 0, true]);","handlingStrategy":"validation","validationCode":"const crib = args[4];\nif (typeof crib !== \"string\" || crib.length === 0) {\n  // enter a known-plaintext fragment\n}","typeGuard":"const hasCrib = (c) => typeof c === \"string\" && c.replace(/[^A-Za-z]/g, \"\").length > 0;","tryCatchPattern":"try { chef.bake(\"Multiple Bombe\", args); }\ncatch (e) { if (e.message === \"Crib cannot be empty\") enterCrib(); else throw e; }","preventionTips":["Always supply a crib known to appear in the ciphertext.","Avoid whitespace-only cribs (they pass length but vanish after filtering).","Validate the crib has at least one letter."],"tags":["crypto","enigma","bombe","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}