zloirock/core-js · error · SyntaxError
Unexpected character after padding
Error message
Unexpected character after padding
What it means
After a complete padded chunk, the base64 spec allows no further data: once padding '=' has been consumed and remaining ASCII whitespace skipped, any non-whitespace character remaining in the string means there is data after the final padding, which is invalid. fromBase64 throws this SyntaxError rather than silently ignoring the trailing content.
Solutions
- Remove all characters after the final '=' in the string before decoding.
- If multiple values are being concatenated, decode each separately instead of joining the base64 strings.
- Trim the string and confirm it ends with padding only when it is genuinely the final chunk.
- Catch SyntaxError and reject the input at your API boundary with a clear message.
Example fix
// before
Uint8Array.fromBase64('QUJDRA==extra'); // Unexpected character after padding
// after
const idx = raw.indexOf('==');
const clean = idx !== -1 ? raw.slice(0, idx + 2) : raw;
Uint8Array.fromBase64(clean); Defensive patterns
Strategy: validation
Validate before calling
function hasNoTrailingData(s) {
const idx = s.indexOf('=');
if (idx === -1) return true;
return /^[\t\n\f\r ]*$/.test(s.slice(idx + 1)); // only whitespace may follow first '='
} Type guard
function isBareBase64(s) {
return typeof s === 'string' && /^[A-Za-z0-9+/=_\-\s]*$/.test(s);
} Try / catch
try {
const bytes = Uint8Array.fromBase64(input);
} catch (e) {
if (e instanceof SyntaxError && e.message.includes('after padding')) {
throw new TypeError('Base64 input has data after final padding — decode values separately');
}
throw e;
} Prevention
- Strip any data-URI prefix and trailing metadata before decoding.
- Never concatenate base64 strings; decode each part individually.
- Trim and validate the string ends exactly at padding.
- Enforce a strict regex (^[A-Za-z0-9+/]*={0,2}$) at the input boundary.
When it happens
Trigger: Uint8Array.fromBase64('AB==C') or any string where a '==' (or 'X=' two-byte chunk) terminated chunk is followed by more non-whitespace characters, with lastChunkHandling 'strict' or 'loose'.
Common situations: Concatenating two base64 strings where the first already ended with padding, embedding base64 inside a larger payload without delimiters, or appending suffixes (e.g. newlines mixed with stray characters, checksums) to encoded values.
Related errors
- Malformed padding: only one =
- Padding is too early
- Malformed padding: exactly one additional character
- Missing padding
- Unexpected character
AI-assisted analysis of zloirock/core-js@84e45fba09 (2026-08-30).
Data as JSON: /api/errors/478f7e0d6a1f10b2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/core-js/internals/uint8-from-base64.js:132
if (chr === '=') {
if (chunk.length < 2) {
throw new SyntaxError('Padding is too early');
}
index = skipAsciiWhitespace(string, index);
if (chunk.length === 2) {
if (index === stringLength) {
if (lastChunkHandling === 'stop-before-partial') {
break;
}
throw new SyntaxError('Malformed padding: only one =');
}
if (at(string, index) === '=') {
++index;
index = skipAsciiWhitespace(string, index);
}
}
if (index < stringLength) {
throw new SyntaxError('Unexpected character after padding');
}
written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, lastChunkHandling === 'strict'), written);
read = stringLength;
break;
}
if (!hasOwn(alphabet, chr)) {
throw new SyntaxError('Unexpected character');
}
var remainingBytes = maxLength - written;
if (remainingBytes === 1 && chunk.length === 2 || remainingBytes === 2 && chunk.length === 3) {
// special case: we can fit exactly the number of bytes currently represented by chunk, so we were just checking for `=`
break;
}
chunk += chr;
if (chunk.length === 4) {
written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, false), written);
chunk = '';View on GitHub (pinned to 84e45fba09)