This error occurs when attempting to decode a base64 string that has incorrect padding. Base64 encoding requires padding to a multiple of 4 characters using the "=" character, and improper padding causes decoding failures in strict validation contexts.
Base64 is an encoding scheme that represents binary data using 64 printable ASCII characters (A-Z, a-z, 0-9, +, /). To ensure the encoded string is always a multiple of 4 characters, padding is added using the "=" character. When Node.js or other libraries encounter a base64 string with invalid padding, they throw an error because the string violates base64 formatting rules. Valid base64 strings must: - Have a length that is a multiple of 4 (including padding) - Use exactly 0, 2, or 3 equals signs for padding - Never use 1 equals sign (which is invalid padding) This error commonly appears when working with cryptographic libraries, JWT tokens, data URLs, or any code that decodes base64-encoded data with strict validation enabled.
Base64 encodes data in groups of 3 bytes (24 bits) into 4 characters (6 bits each). The padding depends on the input length:
Input bytes → Output chars → Padding
1 byte (8 bits) → 2 chars → 2 equals (==)
2 bytes (16 bits) → 3 chars → 1 equals (=) [Note: 1 padding is valid for output]
3 bytes (24 bits) → 4 chars → 0 equalsValid base64 strings after padding are:
- Length % 4 == 0 (always a multiple of 4)
- Ends with 0, 2, or 3 equals signs (1 equals sign is always invalid)
const valid1 = "dGVzdA=="; // 6 chars with 2 padding - valid
const valid2 = "dGVzd==="; // 8 chars with 3 padding - valid
const valid3 = "dGVzd"; // 5 chars with 0 padding - valid (lenient decoders)
const invalid = "dGVzd="; // 6 chars with 1 padding - INVALIDCheck that your base64 string has correct padding before decoding:
function validateBase64(str) {
// Check if string has invalid padding (1 equals sign)
const paddingMatch = str.match(/=+$/);
const paddingCount = paddingMatch ? paddingMatch[0].length : 0;
if (paddingCount === 1) {
console.error("Invalid base64 padding: has 1 equals sign");
return false;
}
// Check if length is multiple of 4 (after padding)
if ((str.length + paddingCount) % 4 !== 0) {
console.error("Invalid base64 length: not a multiple of 4");
return false;
}
return true;
}
const base64String = "dGVzd="; // Invalid
if (validateBase64(base64String)) {
const buffer = Buffer.from(base64String, "base64");
console.log(buffer);
} else {
console.error("Base64 string has invalid padding");
}If your base64 string has incorrect padding, fix it before decoding:
function fixBase64Padding(str) {
// Remove all trailing equals signs
let cleaned = str.replace(/=+$/, "");
// Add correct padding based on string length
const padding = (4 - (cleaned.length % 4)) % 4;
return cleaned + "=".repeat(padding);
}
// Examples
console.log(fixBase64Padding("dGVzd=")); // "dGVzd===" -> may be over-padded
console.log(fixBase64Padding("dGVz")); // "dGVz=" (adds 1) or "dGVz==" depending on content
// Better approach: don't add padding if it's optional
const str = "dGVzd=";
const cleaned = str.replace(/=+$/, "");
const buffer = Buffer.from(cleaned, "base64");
console.log(buffer.toString("utf-8")); // Works with modern Node.jsNote: Modern versions of Node.js are lenient with padding, but older versions and strict decoders require exact padding.
Base64url is used in URLs and JWTs where "=" padding is stripped. When decoding base64url, add padding back:
function decodeBase64Url(str) {
// Replace base64url characters with standard base64
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
// Add padding if needed
const padding = (4 - (base64.length % 4)) % 4;
base64 += "=".repeat(padding);
return Buffer.from(base64, "base64").toString("utf-8");
}
// JWT header example (typically base64url)
const jwtHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
console.log(decodeBase64Url(jwtHeader));
// Output: {"alg":"HS256","typ":"JWT"}Base64url uses "-" and "_" instead of "+" and "/" to be URL-safe.
When receiving base64 strings from external sources (APIs, files, user input), validate them:
function safeBase64Decode(str) {
// Trim whitespace
str = str.trim();
// Check for invalid characters
if (!/^[A-Za-z0-9+/]*={0,3}$/.test(str)) {
throw new Error("Base64 string contains invalid characters");
}
// Check padding
const paddingCount = (str.match(/=/g) || []).length;
if (paddingCount === 1) {
throw new Error("Base64 has invalid padding (1 equals sign)");
}
// Validate total length
if ((str.length) % 4 !== 0) {
throw new Error("Base64 length must be multiple of 4");
}
try {
return Buffer.from(str, "base64");
} catch (e) {
throw new Error("Failed to decode base64: " + e.message);
}
}
// Usage
try {
const buffer = safeBase64Decode("dGVzdA==");
console.log("Decoded:", buffer.toString("utf-8"));
} catch (err) {
console.error("Invalid base64:", err.message);
}If you need to handle base64 strings with various padding styles, use libraries or enable lenient mode:
// For lenient decoding, you can remove padding entirely
function lenientBase64Decode(str) {
// Remove all padding
const cleaned = str.replace(/=+$/, "");
// Modern Node.js handles this fine
try {
return Buffer.from(cleaned, "base64").toString("utf-8");
} catch (e) {
// Fallback: add proper padding
const padded = cleaned + "=".repeat((4 - cleaned.length % 4) % 4);
return Buffer.from(padded, "base64").toString("utf-8");
}
}
// For JSON Web Tokens, use libraries
const jwt = require("jsonwebtoken");
const decoded = jwt.decode(token); // Handles base64url automatically
// For general base64 with various padding, handle both styles
function flexBase64Decode(str) {
try {
return Buffer.from(str, "base64");
} catch (e) {
// Try with padding fixed
const padded = str + "=".repeat((4 - str.length % 4) % 4);
return Buffer.from(padded, "base64");
}
}Base64 Standard (RFC 4648): The standard specifies that padding with "=" is REQUIRED for proper base64 encoding. However, RFC 4648 Section 3.1 defines base64url which is used in URLs and JWTs where padding is often omitted. Node.js is lenient and accepts both padded and unpadded base64, but strict decoders (especially older versions or security-focused libraries) reject invalid padding. Why 1 Equals Sign is Invalid: In base64 encoding, every 3 input bytes produce 4 output characters. If you have remainder bytes: 0 remainder produces 4 chars with 0 padding, 1 remainder produces 2 chars with 2 padding, 2 remainder produces 3 chars with 1 padding. A single "=" always indicates incomplete/truncated data and breaks the 4-character alignment rule. Padding in Different Contexts: Standard Base64 requires padding (RFC 4648), Base64URL (JWT/URLs) has optional padding but when present must be correct, Data URLs always include proper padding, and Crypto Keys typically have strict validation enforced. Security Note: Invalid base64 padding can indicate corrupted or tampered data. In cryptographic contexts, always validate padding strictly and reject invalid strings rather than attempting repair. Performance: For high-volume base64 decoding, pre-validate strings to catch padding errors early. Catching errors during Buffer.from() is more expensive than regex validation. Compatibility: Node.js v14+ are more lenient than earlier versions with base64 padding. If supporting older versions or strict parsers, always ensure proper padding.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams