mozilla/pdf.js · error · FormatError
unsupported encryption algorithm
Error message
unsupported encryption algorithm
What it means
Thrown when the encryption dictionary's V entry is missing, not an integer, or not one of the supported algorithm codes 1, 2, 4, or 5. V selects the encryption algorithm version; V=3 (a deprecated variable-length RC4 variant) and any newer/unknown V value are not implemented. The PDF cannot be decrypted.
Source
Thrown at src/core/crypto.js:1074
}
const hash = calculateMD5(key, 0, i);
return hash.subarray(0, Math.min(n + 5, 16));
}
constructor(dict, fileId, password) {
const filter = dict.get("Filter");
if (!isName(filter, "Standard")) {
throw new FormatError("unknown encryption method");
}
this.filterName = filter.name;
this.dict = dict;
this.#fileId = fileId;
const algorithm = dict.get("V");
if (
!Number.isInteger(algorithm) ||
(algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5)
) {
throw new FormatError("unsupported encryption algorithm");
}
this.algorithm = algorithm;
let keyLength = dict.get("Length");
if (!keyLength) {
// Spec asks to rely on encryption dictionary's Length entry, however
// some PDFs don't have it. Trying to recover.
if (algorithm <= 3) {
// For 1 and 2 it's fixed to 40-bit, for 3 40-bit is a minimal value.
keyLength = 40;
} else {
// Trying to find default handler -- it usually has Length.
const cfDict = dict.get("CF");
const streamCryptoName = dict.get("StmF");
if (cfDict instanceof Dict && streamCryptoName instanceof Name) {
cfDict.suppressEncryption = true; // See comment below.
const handlerDict = cfDict.get(streamCryptoName.name);
keyLength = handlerDict?.get("Length") || 128;
if (keyLength < 40) {View on GitHub (pinned to 5903d58d58)
Solutions
- Re-encrypt the PDF with a supported algorithm (V=2 RC4-40/128, V=4 AES-128/RC4, or V=5 AES-256) via qpdf or Acrobat.
- If V is corrupt, repair the xref/Encrypt dict with qpdf --check or by re-saving through Acrobat.
- Surface an 'unsupported encryption algorithm' user message rather than propagating the FormatError.
Example fix
// before
const doc = await getDocument({ url, password }).promise;
// after — map to a user-facing message
try {
const doc = await getDocument({ url, password }).promise;
} catch (e) {
if (e.message === 'unsupported encryption algorithm') {
throw new Error('Unsupported encryption algorithm (V=' + (e.detail ?? 'unknown') + '). Only V=1,2,4,5 are supported.');
}
throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
const doc = await getDocument({ url }).promise;
} catch (e) {
if (e.name === 'FormatError' && e.message === 'unsupported encryption algorithm') {
notifyUser('Unsupported encryption algorithm; only V=1,2,4,5 are supported.');
return;
}
throw e;
} Prevention
- Re-encrypt PDFs through qpdf --encrypt to V=2, 4, or 5 before ingestion.
- When generating PDFs, pin a supported algorithm version.
- Surface a clear message rather than letting FormatError bubble to the UI.
When it happens
Trigger: Loading a PDF with V=3 (rare legacy producers); a PDF whose /Encrypt dict has a missing or non-integer V entry due to corruption; a PDF using a hypothetical future algorithm code pdf.js has not adopted.
Common situations: Corrupt/truncated Encrypt dict from a bad download or buggy producer; very old PDFs that used V=3 RC4 variants; hand-edited PDFs where V was altered.
Related errors
- unknown encryption method
- Unknown crypto method
- invalid key length
- Invalid crypt filter name.
- No password given
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/09a617dab58a70e4.
Report an issue: GitHub.