denoland/deno · error · TypeError

ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

Error message

The argument 'outputEncoding' is invalid. Received ${inspected}

What it means

crypto.hash's outputEncoding (the third argument as a string, or the outputEncoding field of the options object) must name a known encoding. It is normalized like Buffer encodings; when normalizeEncoding() returns undefined only the special value 'buffer' (matched case-insensitively via toLowerCase) is rescued — every other unknown name throws ERR_INVALID_ARG_VALUE.

Source

Thrown at ext/node/polyfills/crypto.ts:173

  if (typeof outputEncodingOrOptions === "object") {
    outputEncoding = outputEncodingOrOptions.outputEncoding ?? "hex";
    outputLength = outputEncodingOrOptions.outputLength;
  } else {
    outputEncoding = outputEncodingOrOptions;
  }

  let normalized = outputEncoding;
  // Fast case: if it's 'hex', we don't need to validate it further.
  if (outputEncoding !== "hex") {
    validateString(outputEncoding, "outputEncoding");
    normalized = normalizeEncoding(outputEncoding);
    // If the encoding is invalid, normalizeEncoding() returns undefined.
    if (normalized === undefined) {
      // 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`,
      );
    }
  }

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Use a supported encoding: 'hex', 'base64', 'base64url', 'utf8'/'utf-8', 'utf16le', 'latin1', 'ascii', 'binary'
  2. Pass 'buffer' (any case) to get a Buffer back
  3. Validate encoding names against an allowlist before calling

Example fix

// before
crypto.hash("sha256", "x", "base62");
// after
crypto.hash("sha256", "x", "base64url");
Defensive patterns

Strategy: validation

Validate before calling

const OK_ENCODINGS = new Set([
  "hex", "base64", "base64url", "utf8", "utf-8", "utf16le",
  "latin1", "ascii", "binary", "buffer",
]);
const enc = String(encoding).toLowerCase();
if (!OK_ENCODINGS.has(enc)) throw new TypeError(`unsupported encoding: ${encoding}`);

Type guard

const isOutputEncoding = (e) => typeof e === "string" && OK_ENCODINGS.has(e.toLowerCase());

Try / catch

try { return crypto.hash(algo, data, enc); }
catch (e) {
  if (e.code === "ERR_INVALID_ARG_VALUE" && e.message.includes("outputEncoding")) {
    return crypto.hash(algo, data, "hex");
  } else throw e;
}

Prevention

When it happens

Trigger: crypto.hash('sha256', 'x', 'base62'); 'hexadecimal'; 'utf8 ' with trailing space; '' (empty string). The fast path skips validation only for the exact string 'hex'; everything else goes through normalizeEncoding.

Common situations: Typos in config-driven encoding names; assuming custom encodings like 'base62' or 'ascii85' exist; casing is forgiving ('BUFFER' works) but spelling and whitespace are not.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/0049ac74fc2b27d1. Report an issue: GitHub.