{"record":{"id":"68e9cde801081817","repo":"gchq/CyberChef","slug":"alphabet-must-be-of-length-58","errorCode":null,"errorMessage":"Alphabet must be of length 58","messagePattern":"Alphabet must be of length 58","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/FromBase58.mjs","lineNumber":69,"sourceCode":"            },\n        ];\n    }\n\n    /**\n     * @param {string} input\n     * @param {Object[]} args\n     * @returns {byteArray}\n     */\n    run(input, args) {\n        let alphabet = args[0] || ALPHABET_OPTIONS[0].value;\n        const removeNonAlphaChars = args[1] === undefined ? true : args[1],\n            result = [];\n\n        alphabet = Utils.expandAlphRange(alphabet).join(\"\");\n\n        if (alphabet.length !== 58 ||\n            [].unique.call(alphabet).length !== 58) {\n            throw new OperationError(\"Alphabet must be of length 58\");\n        }\n\n        if (input.length === 0) return [];\n\n        let zeroPrefix = 0;\n        for (let i = 0; i < input.length && input[i] === alphabet[0]; i++) {\n            zeroPrefix++;\n        }\n\n        [].forEach.call(input, function(c, charIndex) {\n            const index = alphabet.indexOf(c);\n\n            if (index === -1) {\n                if (removeNonAlphaChars) {\n                    return;\n                } else {\n                    throw new OperationError(`Char '${c}' at position ${charIndex} not in alphabet`);\n                }","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/FromBase58.mjs#L51-L87","documentation":"Thrown by From Base58 when the supplied alphabet, after expandAlphRange expansion, does not have exactly 58 unique characters. Base58 by definition requires a 58-symbol alphabet; both the length and uniqueness are checked. This is an argument/configuration error, independent of the input data.","triggerScenarios":"Providing a custom alphabet with fewer or more than 58 chars; an alphabet with duplicate characters; an A-Z range expansion that produced unexpected length; selecting a preset then editing it down.","commonSituations":"User customizes the alphabet field incorrectly; confusion between Bitcoin and Ripple alphabets mixed together; copy-paste truncation of the alphabet string.","solutions":["Use one of the built-in alphabet presets (Bitcoin, Ripple) instead of a custom one.","If custom, ensure exactly 58 unique characters with no duplicates.","Double-check expandAlphRange semantics if using ranges like A-Z."],"exampleFix":"// before: 57-char alphabet\nfromBase58.run(input, ['123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuv']) // 57\n// after: standard Bitcoin alphabet (58 unique)\nfromBase58.run(input, ['123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'])","handlingStrategy":"validation","validationCode":"const alphabet = Utils.expandAlphRange(args[0]).join('');\nconst unique = new Set(alphabet.split(''));\nif (alphabet.length !== 58 || unique.size !== 58) {\n  // use a built-in preset; do not call fromBase58.run()\n}","typeGuard":"function isValidBase58Alphabet(a) {\n  const s = a; // post-expansion string\n  return s.length === 58 && new Set(s).size === 58;\n}","tryCatchPattern":"try {\n  fromBase58.run(input, args);\n} catch (e) {\n  if (e.type === 'OperationError' && /Alphabet must be of length 58/.test(e.message)) {\n    // reset alphabet to the Bitcoin/Ripple preset\n  } else throw e;\n}","preventionTips":["Prefer built-in alphabet presets over hand-typed alphabets.","Validate 58 unique characters before invoking.","Account for expandAlphRange when using A-Z style ranges."],"tags":["base58","alphabet","argument-validation","config"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}