{"record":{"id":"90ba4526a8e72141","repo":"zloirock/core-js","slug":"extra-bits","errorCode":null,"errorMessage":"Extra bits","messagePattern":"Extra bits","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/core-js/internals/uint8-from-base64.js","lineNumber":48,"sourceCode":"\n  if (chunkLength < 4) {\n    chunk += chunkLength === 2 ? 'AA' : 'A';\n  }\n\n  var triplet = (alphabet[at(chunk, 0)] << 18)\n    + (alphabet[at(chunk, 1)] << 12)\n    + (alphabet[at(chunk, 2)] << 6)\n    + alphabet[at(chunk, 3)];\n\n  var chunkBytes = [\n    (triplet >> 16) & 255,\n    (triplet >> 8) & 255,\n    triplet & 255\n  ];\n\n  if (chunkLength === 2) {\n    if (throwOnExtraBits && chunkBytes[1] !== 0) {\n      throw new SyntaxError('Extra bits');\n    }\n    return [chunkBytes[0]];\n  }\n\n  if (chunkLength === 3) {\n    if (throwOnExtraBits && chunkBytes[2] !== 0) {\n      throw new SyntaxError('Extra bits');\n    }\n    return [chunkBytes[0], chunkBytes[1]];\n  }\n\n  return chunkBytes;\n};\n\nvar writeBytes = function (bytes, elements, written) {\n  var elementsLength = elements.length;\n  for (var index = 0; index < elementsLength; index++) {\n    bytes[written + index] = elements[index];","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/zloirock/core-js/blob/84e45fba098dd3a177d5cf2247d06ab8e98d3790/packages/core-js/internals/uint8-from-base64.js#L30-L66","documentation":"In Uint8Array.fromBase64 (as polyfilled by core-js), a final base64 chunk of 2 characters encodes 2 bytes but still carries 6 leftover bits of the third byte. With lastChunkHandling 'strict', if those leftover bits are non-zero the input isn't canonical base64, so a SyntaxError 'Extra bits' is thrown. 'loose' mode ignores this.","triggerScenarios":"`Uint8Array.fromBase64(str, { lastChunkHandling: 'strict' })` where the string ends in a 2-char final chunk (no '==') whose low bits are non-zero, e.g. 'QQ==' is fine but 'QR==' style non-canonical endings throw.","commonSituations":"Data encoded by a non-canonical or hand-rolled encoder that didn't zero the trailing bits, strings truncated by a regex/split that dropped padding, or switching code from loose/decoder defaults to strict mode.","solutions":["Use lastChunkHandling: 'loose' (the default) if you accept non-canonical input.","Re-encode the data at the source with a canonical base64 encoder.","Strip/normalize the final partial chunk before decoding.","Drop 'strict' only if bitwise-exact round-tripping isn't required for security (strict exists to catch tampering)."],"exampleFix":"// before\nUint8Array.fromBase64('QR==', { lastChunkHandling: 'strict' }); // SyntaxError: Extra bits\n// after\nUint8Array.fromBase64('QQ==', { lastChunkHandling: 'strict' }); // canonical, ok","handlingStrategy":"validation","validationCode":"function isCanonicalTail2(b64, alphabet) {\n  const m = b64.match(/(..?)$/);\n  return m ? true : false; // prefer re-encoding: canonical iff low bits zero\n}\n// simplest pre-check: re-encode decoded bytes and compare when using strict\nconst bytes = Uint8Array.fromBase64(b64); // loose\nif (btoa(String.fromCharCode(...bytes)) !== b64) throw new Error('non-canonical base64');","typeGuard":"function isCanonicalBase64(s) {\n  try { return btoa(String.fromCharCode(...Uint8Array.fromBase64(s))) === s; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  bytes = Uint8Array.fromBase64(b64, { lastChunkHandling: 'strict' });\n} catch (e) {\n  if (e instanceof SyntaxError && e.message === 'Extra bits') {\n    bytes = Uint8Array.fromBase64(b64); // loose fallback\n  } else throw e;\n}","preventionTips":["Encode with a canonical base64 implementation (zero trailing bits).","Only use 'strict' when canonicality matters (e.g. signature verification).","Round-trip test your encoder: decode then re-encode and compare strings."],"tags":["core-js","base64","uint8array","syntaxerror"],"backgroundTag":"base64-extra-bits","analyzedSha":"84e45fba098dd3a177d5cf2247d06ab8e98d3790","analyzedAt":"2026-08-30T20:36:10.323Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}