Hmbown/CodeWhale · error · Error

invalid base64

Error message

invalid base64

What it means

strictBase64 validates a string as canonical standard base64 before decoding: non-empty, length multiple of 4, only A-Za-z0-9+/ with up to two trailing '=', and length within the bound implied by maxBytes. The first throw happens when the input fails these format checks — this bounds allocation and rejects ambiguous encodings before Buffer decoding.

Solutions

  1. Convert base64url to standard base64: replace '-'→'+' and '_'→'/', pad with '=' to a multiple of 4
  2. Strip whitespace and any scheme prefix from the value
  3. Check that the string length is a multiple of 4 and the charset matches /^[A-Za-z0-9+/]*={0,2}$/

Example fix

// before
strictBase64('a-b_c=', 32); // base64url chars
// after
const std = ('a-b_c='.replace(/-/g, '+').replace(/_/g, '/') + '==').slice(0, Math.ceil('a-b_c='.length / 4) * 4);
strictBase64(std, 32);
Defensive patterns

Strategy: validation

Validate before calling

const looksLikeBase64 = (s) => typeof s === 'string' && s.length > 0 && s.length % 4 === 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(s);
if (!looksLikeBase64(value)) throw new Error('not canonical base64');

Type guard

const isCanonicalB64Shape = (v) => typeof v === 'string' && v.length > 0 && v.length % 4 === 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(v);

Try / catch

try { key = strictBase64(value, 32); } catch (e) { if (e.message === 'invalid base64') { value = normalizeToStdBase64(value); key = strictBase64(value, 32); } else throw e; }

Prevention

When it happens

Trigger: Passing a value that is not a string, an empty string, a string containing '-'/'_' (base64url alphabet), whitespace/newlines, or a length that is not a multiple of 4.

Common situations: Pasting URL-safe base64 (JWT segments) where standard base64 is required, copying a key with line breaks or a 'base64:' prefix, or passing undefined/null.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/a1d9fa6d5d3ee5c2. Report an issue: GitHub.

Appendix: source

Thrown at web/scripts/facts-publish.mjs:90

  // Ed25519 SPKI DER is a fixed 12-byte prefix followed by the 32-byte key.
  return spki.subarray(spki.length - 32);
}

export function publicKeyObjectFromRaw(rawB64) {
  const raw = strictBase64(rawB64, 32);
  if (raw.length !== 32) throw new Error("public key must decode to 32 bytes");
  const prefix = Buffer.from("302a300506032b6570032100", "hex");
  return createPublicKey({ key: Buffer.concat([prefix, raw]), type: "spki", format: "der" });
}

export function signPayload(privateKey, keyId, payloadBytes) {
  return sign(null, signingMessage(keyId, payloadBytes), privateKey);
}

/** Canonical base64 is checked before decoding to bound allocation. */
export function strictBase64(value, maxBytes) {
  if (typeof value !== "string" || !value.length || value.length > 4 * Math.ceil(maxBytes / 3) ||
      (value.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(value))) throw new Error("invalid base64");
  const bytes = Buffer.from(value, "base64");
  if (bytes.length > maxBytes || bytes.toString("base64") !== value) throw new Error("invalid base64");
  return bytes;
}

export function utcTime(value) {
  if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/.test(value)) return null;
  const time = Date.parse(value);
  return Number.isFinite(time) && new Date(time).toISOString().slice(0, 19) === value.slice(0, 19) ? time : null;
}

export function verifyEnvelope(envelope, publicKeyB64) {
  const errors = [];
  if (!isPlainObject(envelope)) return { ok: false, errors: ["envelope must be an object"] };
  if (envelope.envelope !== ENVELOPE_VERSION) errors.push("unsupported envelope version");
  if (envelope.alg !== "ed25519") errors.push("unsupported signature algorithm");
  if (typeof envelope.key_id !== "string" || !KEY_ID_RE.test(envelope.key_id)) errors.push("bad key_id");
  if (envelope.schema_version !== SCHEMA_VERSION) errors.push("unsupported schema version");

View on GitHub (pinned to 433685b202)