denoland/deno · error · Error
Output length ${outputLength} is invalid for ${algoLower}, w
Error message
Output length ${outputLength} is invalid for ${algoLower}, which does not support XOF What it means
When crypto.hash receives outputLength, only XOF algorithms (shake128, shake256) accept arbitrary lengths. For fixed-length algorithms the polyfill computes the expected digest size by hashing an empty string and requires outputLength to equal it exactly; otherwise it throws a plain Error (no code property) whose message ends with 'which does not support XOF'.
Source
Thrown at ext/node/polyfills/crypto.ts:187
// normalizeEncoding() doesn't handle 'buffer'.
if (StringPrototypeToLowerCase(outputEncoding) === "buffer") {
normalized = "buffer";
} else {
throw new ERR_INVALID_ARG_VALUE("outputEncoding", outputEncoding);
}
}
}
const algoLower = StringPrototypeToLowerCase(algorithm);
const isXof = algoLower === "shake128" || algoLower === "shake256";
if (outputLength != null && !isXof) {
// For non-XOF hashes, outputLength must match the algorithm's digest size.
const testHash = createHash(algorithm);
testHash.update("");
const expectedLen = testHash.digest().length;
if (outputLength !== expectedLen) {
throw new Error(
`Output length ${outputLength} is invalid for ${algoLower}, which does not support XOF`,
);
}
}
const h = createHash(
algorithm,
outputLength != null ? { outputLength } : undefined,
);
h.update(data);
if (outputLength === 0) {
return normalized === "buffer" ? globalThis.Buffer.alloc(0) : "";
}
return h.digest(outputEncoding);
}
View on GitHub (pinned to 89f33cbef2)
Solutions
- Omit outputLength for fixed-length algorithms like sha256/sha512
- Switch to a XOF: crypto.hash('shake128', data, { outputLength: 16 })
- To shorten a standard digest, slice the returned Buffer instead of setting outputLength
Example fix
// before
crypto.hash("sha256", data, { outputLength: 16 });
// after
crypto.hash("shake128", data, { outputLength: 16 });
// or truncate a fixed digest:
// crypto.hash("sha256", data, "buffer").subarray(0, 16) Defensive patterns
Strategy: validation
Validate before calling
const XOF = new Set(["shake128", "shake256"]);
function normalizeHashOptions(algorithm, opts = {}) {
if (opts.outputLength != null && !XOF.has(algorithm.toLowerCase())) {
delete opts.outputLength; // fixed-length algorithms ignore it
}
return opts;
} Type guard
const supportsOutputLength = (algo) => typeof algo === "string" && /^shake(128|256)$/i.test(algo);
Try / catch
try { return crypto.hash(algo, data, opts); }
catch (e) {
if (/does not support XOF/.test(e.message)) {
return crypto.hash(algo, data, "buffer").subarray(0, opts.outputLength); // truncate instead
} else throw e;
} Prevention
- Treat outputLength as a shake-family-only feature
- Truncate standard digests with Buffer#subarray, not outputLength
- Compare algorithm names case-insensitively when branching on XOF support
When it happens
Trigger: crypto.hash('sha256', 'x', { outputLength: 16 }) — sha256 always yields 32 bytes, so this throws; { outputLength: 32 } would pass; outputLength: 0 skips the length check entirely and returns empty output. outputLength != null (not undefined/null) is what arms the check.
Common situations: Reusing an options bag written for shake128/shake256 with sha2/sha3 algorithms; assuming outputLength truncates the digest (it does not — only XOFs can vary output); sharing hashing helpers across algorithm families.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_VALUE
- If "keyFormat" is specified, it must be "pem": received "${k
- ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED
- ERR_CRYPTO_FIPS_FORCED
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/1ebd0331dc2960e4.
Report an issue: GitHub.