{"record":{"id":"1ebd0331dc2960e4","repo":"denoland/deno","slug":"output-length-outputlength-is-invalid-for-alg","errorCode":null,"errorMessage":"Output length ${outputLength} is invalid for ${algoLower}, which does not support XOF","messagePattern":"Output length (.+?) is invalid for (.+?), which does not support XOF","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/crypto.ts","lineNumber":187,"sourceCode":"      // normalizeEncoding() doesn't handle 'buffer'.\n      if (StringPrototypeToLowerCase(outputEncoding) === \"buffer\") {\n        normalized = \"buffer\";\n      } else {\n        throw new ERR_INVALID_ARG_VALUE(\"outputEncoding\", outputEncoding);\n      }\n    }\n  }\n\n  const algoLower = StringPrototypeToLowerCase(algorithm);\n  const isXof = algoLower === \"shake128\" || algoLower === \"shake256\";\n\n  if (outputLength != null && !isXof) {\n    // For non-XOF hashes, outputLength must match the algorithm's digest size.\n    const testHash = createHash(algorithm);\n    testHash.update(\"\");\n    const expectedLen = testHash.digest().length;\n    if (outputLength !== expectedLen) {\n      throw new Error(\n        `Output length ${outputLength} is invalid for ${algoLower}, which does not support XOF`,\n      );\n    }\n  }\n\n  const h = createHash(\n    algorithm,\n    outputLength != null ? { outputLength } : undefined,\n  );\n  h.update(data);\n\n  if (outputLength === 0) {\n    return normalized === \"buffer\" ? globalThis.Buffer.alloc(0) : \"\";\n  }\n\n  return h.digest(outputEncoding);\n}\n","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/crypto.ts#L169-L205","documentation":"crypto.hash() supports outputLength only for XOF algorithms ('shake128', 'shake256'). For any other algorithm, outputLength must equal the native digest size, or a plain Error is thrown. This error has no code property.","triggerScenarios":"crypto.hash('sha256', data, { outputLength: 16 }) with a truncated length. Using one options object across all algorithms and leaving outputLength set. Assuming sha2 supports truncation like SHAKE.","commonSituations":"A shared helper written for SHAKE reuse with fixed-width hashes. Code migrated from a library where arbitrary digest truncation was allowed. outputLength left over from a test fixture.","solutions":["Omit outputLength for fixed-size algorithms such as sha256 and sha512.","Switch to 'shake128' or 'shake256' when you need variable output length.","If the field must be present, match the digest size: 32 for sha256, 64 for sha512."],"exampleFix":"// before\ncrypto.hash('sha256', data, { outputLength: 16 });\n\n// after\ncrypto.hash('shake128', data, { outputLength: 16 });","handlingStrategy":"validation","validationCode":"const XOF = new Set(['shake128', 'shake256']);\nconst algo = 'sha256';\nconst opts = XOF.has(algo.toLowerCase()) ? { outputLength: 16 } : {};","typeGuard":"function isXof(algo: string): boolean { const a = algo.toLowerCase(); return a === 'shake128' || a === 'shake256'; }","tryCatchPattern":null,"preventionTips":["Set outputLength only in code paths that use shake128 or shake256.","Document in the helper signature that outputLength is XOF-only."],"tags":["crypto","hash","xof","shake"],"backgroundTag":"invalid-argument-value","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}