zloirock/core-js · error · SyntaxError

Unexpected character

Error message

Unexpected character

What it means

fromBase64 only accepts valid base64 characters from the chosen alphabet (standard or base64url, plus '=' padding, with whitespace allowed). When the current character is not found in the alphabet map (hasOwn check fails), the library throws this SyntaxError, per the spec's requirement to reject invalid characters rather than skip them.

Source

Thrown at packages/core-js/internals/uint8-from-base64.js:139

          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 = '';
      read = index;
      if (written === maxLength) {
        break;
      }
    }
  }
  if (!into) bytes.length = written;

View on GitHub (pinned to 84e45fba09)

Solutions

  1. Strip the 'data:...;base64,' prefix and decode only the substring after the comma.
  2. Pass { alphabet: 'base64url' } if the input uses '-' and '_' characters.
  3. Sanitize the input: remove quotes, commas, and other delimiters; keep only A-Za-z0-9+/= (or -_ for base64url) plus allowed whitespace.
  4. Wrap in try/catch for SyntaxError and log the offending character position for debugging.

Example fix

// before
const bytes = Uint8Array.fromBase64(token); // token uses '-' and '_': Unexpected character
// after
const bytes = Uint8Array.fromBase64(token, { alphabet: 'base64url', lastChunkHandling: 'strict' });
Defensive patterns

Strategy: type-guard

Validate before calling

const BASE64_RE = /^[A-Za-z0-9+/=\s]+$/;
const BASE64URL_RE = /^[A-Za-z0-9\-_=\s]+$/;
function isBase64AlphabetSafe(s, url = false) {
  if (typeof s !== 'string') return false;
  const re = url ? BASE64URL_RE : BASE64_RE;
  if (!re.test(s)) return false;
  const hasUrl = /[-_]/.test(s), hasStd = /[+/]/.test(s);
  return !(hasUrl && hasStd); // mixed alphabets are never valid
}

Type guard

function isDecodableBase64String(s) {
  return typeof s === 'string' &&
    (/^[A-Za-z0-9+/=\s]*$/.test(s) || /^[A-Za-z0-9\-_=\s]*$/.test(s));
}

Try / catch

let bytes;
try {
  bytes = Uint8Array.fromBase64(bare, { alphabet: isBase64Url(bare) ? 'base64url' : 'base64' });
} catch (e) {
  if (e instanceof SyntaxError && e.message === 'Unexpected character') {
    throw new TypeError('Input contains characters outside the base64 alphabet');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling Uint8Array.fromBase64 with characters outside the alphabet: '-' or '_' when using the standard alphabet, '+' or '/' with alphabet: 'base64url', or any stray character like quotes, '<', ',', or a leading BOM/data-URI prefix such as 'data:text/plain;base64,'.

Common situations: Passing a full data URL instead of the bare base64 payload, base64url-encoded tokens decoded without { alphabet: 'base64url' }, JSON/CSV delimiters accidentally included, or whitespace characters not covered when 'strict' handling disallows them mid-string.

Related errors


AI-assisted analysis of zloirock/core-js@84e45fba09 (2026-08-30). Data as JSON: /api/errors/d52fbffd1e1a0789. Report an issue: GitHub.