{"record":{"id":"5a3b2dcb8bcf057a","repo":"gchq/CyberChef","slug":"crib-cannot-be-empty","errorCode":null,"errorMessage":"Crib cannot be empty","messagePattern":"Crib cannot be empty","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/Bombe.mjs","lineNumber":135,"sourceCode":"        const offset = args[7];\n        const check = args[8];\n        const rotors = [];\n        for (let i=0; i<4; i++) {\n            if (i === 0 && model === \"3-rotor\") {\n                // No fourth rotor\n                continue;\n            }\n            let rstr = args[i + 1];\n            // The Bombe doesn't take stepping into account so we'll just ignore it here\n            if (rstr.includes(\"<\")) {\n                rstr = rstr.split(\"<\", 2)[0];\n            }\n            rotors.push(rstr);\n        }\n        // Rotors are handled in reverse\n        rotors.reverse();\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        const reflector = new Reflector(reflectorstr);\n        let update;\n        if (isWorkerEnvironment()) {\n            update = this.updateStatus;\n        } else {\n            update = undefined;\n        }\n        const bombe = new BombeMachine(rotors, reflector, ciphertext, crib, check, update);\n        const result = bombe.run();\n        return {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/Bombe.mjs#L117-L153","documentation":"The Bombe attack requires a known-plaintext 'crib' to test against ciphertext. If the crib argument is empty after extraction, the operation cannot form any hypothesis and throws immediately, before rotor setup.","triggerScenarios":"Calling Bombe.run with an empty crib argument string (length 0 before any character filtering).","commonSituations":"User leaves the crib field blank; UI default empty string; the crib variable was not bound from the recipe.","solutions":["Supply a non-empty crib (the suspected plaintext fragment) as an argument.","Validate crib.length > 0 in the UI before allowing the recipe to run.","Confirm the argument order matches the operation's ingList."],"exampleFix":"// before\ncrib = ''\n// after\ncrib = 'WETTER'","handlingStrategy":"validation","validationCode":"if (!crib || crib.length === 0) throw new Error('Crib is required for the Bombe');","typeGuard":"function hasCrib(c) { return typeof c === 'string' && c.length > 0; }","tryCatchPattern":null,"preventionTips":["Require a non-empty crib in the UI before enabling run.","Bind the crib argument explicitly from the recipe.","Educate users that the Bombe needs known plaintext."],"tags":["cipher","bombe","validation","crib"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}