denoland/deno · error · NodeError

ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH

ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH

Error message

Invalid XOF digest length

What it means

When a Hash is created with an options.outputLength and the algorithm is not an eXtendable-Output-Function, the native op rejects the length with 'Output length mismatch for non-extendable algorithm', which the polyfill remaps to Node's ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH ('Invalid XOF digest length'). Only XOFs (shake128, shake256) can produce caller-chosen digest sizes.

Source

Thrown at ext/node/polyfills/internal/crypto/hash.ts:125

    warnedShakeOutputLength = true;
    const process = lazyProcess().default;
    process.emitWarning(
      "Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.",
      "DeprecationWarning",
      "DEP0198",
    );
  }

  try {
    this[kHandle] = isCopy
      ? op_node_hash_clone(algorithm, xofLen)
      : op_node_create_hash(algoLower, xofLen);
  } catch (err) {
    // TODO(lucacasonato): don't do this
    if (
      err.message === "Output length mismatch for non-extendable algorithm"
    ) {
      throw new NodeError(
        "ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH",
        "Invalid XOF digest length",
      );
    } else {
      throw err;
    }
  }

  if (this[kHandle] === null) throw new ERR_CRYPTO_HASH_FINALIZED();

  const LazyTransform = lazyLazyTransform().default;
  ReflectApply(LazyTransform, this, [options]);
}

interface Hash {
  [kHandle]: object;
  [kFinalized]: boolean;
}

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Remove options.outputLength for fixed-length algorithms (sha1/sha256/sha384/sha512/md5) and slice the digest instead: digest.subarray(0, 16)
  2. Switch to 'shake128' or 'shake256' when a variable-length digest is genuinely required
  3. If using shake, pass an explicit outputLength every time (omitting it is deprecated via DEP0198)

Example fix

// before
const d = crypto.createHash('sha256', { outputLength: 16 }).update(data).digest();

// after
const d = crypto.createHash('sha256').update(data).digest().subarray(0, 16);
Defensive patterns

Strategy: validation

Validate before calling

const XOF = new Set(['shake128', 'shake256']);
if (options?.outputLength !== undefined && !XOF.has(algorithm)) {
  throw new RangeError(`outputLength is only valid for XOF algorithms, not ${algorithm}`);
}
const h = crypto.createHash(algorithm, options);

Type guard

const isXofAlgorithm = (a: string): boolean => a === 'shake128' || a === 'shake256';

Try / catch

catch (e) { if ((e as NodeJS.ErrnoException).code === 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH') { /* drop outputLength or switch to shake128/256, then retry */ } throw e; }

Prevention

When it happens

Trigger: crypto.createHash('sha256', { outputLength: 16 }); or h.copy({ outputLength: 8 }) on a sha256 hash. Also a shake digest whose outputLength is outside the algorithm's allowed range triggers the same OpenSSL error.

Common situations: Truncating a digest to fit a fixed-size column or token and assuming every algorithm supports outputLength; code written against shake128 ported to sha256 without dropping the option; copying a configurable hash factory across algorithms.

Understand the failure class

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/6c1c7be6c590525c. Report an issue: GitHub.