{"record":{"id":"e93a64c777ad7f68","repo":"gchq/CyberChef","slug":"error-base64-not-padded-to-a-multiple-of-4","errorCode":null,"errorMessage":"Error: Base64 not padded to a multiple of 4.","messagePattern":"Error: Base64 not padded to a multiple of 4\\.","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Base64.mjs","lineNumber":121,"sourceCode":"\n    if (strictMode) {\n        // Check for incorrect lengths (even without padding)\n        if (data.length % 4 === 1) {\n            throw new OperationError(`Error: Invalid Base64 input length (${data.length}). Cannot be 4n+1, even without padding chars.`);\n        }\n\n        if (alphabet.length === 65) { // Padding character included\n            const pad = alphabet.charAt(64);\n            const padPos = data.indexOf(pad);\n            if (padPos >= 0) {\n                // Check that the padding character is only used at the end and maximum of twice\n                if (padPos < data.length - 2 || data.charAt(data.length - 1) !== pad) {\n                    throw new OperationError(`Error: Base64 padding character (${pad}) not used in the correct place.`);\n                }\n\n                // Check that input is padded to the correct length\n                if (data.length % 4 !== 0) {\n                    throw new OperationError(\"Error: Base64 not padded to a multiple of 4.\");\n                }\n            }\n        }\n    }\n\n    const output = [];\n    let chr1, chr2, chr3,\n        enc1, enc2, enc3, enc4,\n        i = 0;\n\n    while (i < data.length) {\n        // Including `|| null` forces empty strings to null so that indexOf returns -1 instead of 0\n        enc1 = alphabet.indexOf(data.charAt(i++) || null);\n        enc2 = alphabet.indexOf(data.charAt(i++) || null);\n        enc3 = alphabet.indexOf(data.charAt(i++) || null);\n        enc4 = alphabet.indexOf(data.charAt(i++) || null);\n\n        if (strictMode && (enc1 < 0 || enc2 < 0 || enc3 < 0 || enc4 < 0)) {","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Base64.mjs#L103-L139","documentation":"Thrown by fromBase64() in src/core/lib/Base64.mjs:121 under strictMode when a padding character is present and correctly positioned at the end, but the total input length is not a multiple of 4. Valid Base64 with padding is always a multiple of 4 characters; a remainder indicates missing or excess characters. This guard runs after the position check at line 115.","triggerScenarios":"strictMode=true, alphabet length 65, pad present at the tail, but data.length % 4 !== 0. Example: fromBase64('ABC=', 'A-Za-z0-9+/=', 'byteArray', false, true) — length 4 passes, but fromBase64('ABCDE=', ..., true) length 6 % 4 === 2 throws. Also 'A=' (length 2) or 'ABCDEFG=' (length 8 is fine; length 7 not).","commonSituations":"Trailing whitespace counted because removeNonAlphChars=false; partial truncation that left a dangling '='; copy-paste that duplicated or dropped a char between the data and the pad; user-added '=' to 'fix' an unpadded string without extending to a multiple of 4.","solutions":["Strip whitespace/newlines with removeNonAlphChars=true before the length check.","Re-derive the string from the source and re-pad so total length % 4 === 0.","If the input is meant to be unpadded, remove the '=' entirely rather than leaving a malformed pad.","Fall back to strictMode=false when you cannot guarantee canonical padding."],"exampleFix":"// before - length 6 is not a multiple of 4\nfromBase64('ABCDE=', 'A-Za-z0-9+/=', 'byteArray', false, true);\n\n// after - pad to a multiple of 4\nfromBase64('ABCDEF==', 'A-Za-z0-9+/=', 'byteArray', false, true); // wait, still wrong\n// correct: re-encode or use a canonical string of length %4===0\nfromBase64(canonicalStr, 'A-Za-z0-9+/=', 'byteArray', true, true);","handlingStrategy":"validation","validationCode":"function isPaddedToMultipleOf4(data, pad) {\n  return data.indexOf(pad) < 0 || data.length % 4 === 0;\n}","typeGuard":"function isCanonicalBase64WithPad(s) {\n  return typeof s === 'string' && (s.indexOf('=') < 0 || (s.length % 4 === 0 && /^[A-Za-z0-9+/]+={0,2}$/.test(s)));\n}","tryCatchPattern":"try {\n  fromBase64(input, 'A-Za-z0-9+/=', 'byteArray', false, true);\n} catch (e) {\n  if (e instanceof OperationError && /not padded to a multiple of 4/.test(e.message)) {\n    input = input.replace(/=+$/, ''); // strip and re-pad correctly\n    while (input.length % 4 !== 0) input += '=';\n  }\n}","preventionTips":["When adding padding, extend the string to a multiple of 4 exactly.","Strip then re-pad rather than appending '=' to a wrong-length string.","Keep removeNonAlphChars=true so trailing whitespace does not throw off the modulo."],"tags":["base64","decoding","padding","strict-mode","input-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}