{"record":{"id":"9d32aaa979f64605","repo":"denoland/deno","slug":"usages-cannot-be-empty-when-importing-a-secret-key","errorCode":null,"errorMessage":"Usages cannot be empty when importing a secret key.","messagePattern":"Usages cannot be empty when importing a secret key\\.","errorType":"exception","errorClass":"DOMException","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/keys.ts","lineNumber":799,"sourceCode":"          \"SyntaxError\",\n        );\n      }\n      if (\n        usages.length > 0 &&\n        ArrayPrototypeSome(\n          usages,\n          (u: string) =>\n            !ArrayPrototypeIncludes([\"deriveKey\", \"deriveBits\"], u),\n        )\n      ) {\n        throw new DOMException(\n          \"Unsupported key usage for an HKDF key\",\n          \"SyntaxError\",\n        );\n      }\n    } else if (algName === \"HMAC\") {\n      if (usages.length === 0) {\n        throw new DOMException(\n          \"Usages cannot be empty when importing a secret key.\",\n          \"SyntaxError\",\n        );\n      }\n      const alg = algorithm as { length?: number };\n      if (alg.length !== undefined && alg.length === 0) {\n        throw new DOMException(\n          \"HmacImportParams.length cannot be 0\",\n          \"DataError\",\n        );\n      }\n    } else if (algName === \"KMAC128\" || algName === \"KMAC256\") {\n      if (usages.length === 0) {\n        throw new DOMException(\n          \"Usages cannot be empty when importing a secret key.\",\n          \"SyntaxError\",\n        );\n      }","sourceCodeStart":781,"sourceCodeEnd":817,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/keys.ts#L781-L817","documentation":"Thrown by SecretKeyObject.toCryptoKey() when converting a secret KeyObject to a CryptoKey with algorithm 'HMAC' and an empty usages array. WebCrypto import rules require at least one usage, because a key that can perform no operation indicates a caller bug. The polyfill surfaces this as a DOMException of type SyntaxError before attempting the import.","triggerScenarios":"createSecretKey(secret).toCryptoKey({ name: 'HMAC', hash: 'SHA-256' }, false, []) — third argument is an empty array.","commonSituations":"Generic import wrappers whose usages parameter defaults to []; refactors that drop the usages argument; code that builds usages conditionally and ends up with zero entries for some key types.","solutions":["Pass at least one valid usage — typically ['sign'] or ['sign','verify'] for HMAC","Audit wrapper defaults so usages can never be an empty array","Derive the usages list from the operation the key will actually perform"],"exampleFix":"// before\nconst key = createSecretKey(secret).toCryptoKey({ name: 'HMAC', hash: 'SHA-256' }, false, []); // throws\n\n// after\nconst key = createSecretKey(secret).toCryptoKey({ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);","handlingStrategy":"validation","validationCode":"if (usages.length === 0) {\n  throw new Error(`HMAC key requires usages; got none (caller: ${callerId})`);\n}\nconst key = secretKeyObject.toCryptoKey({ name: 'HMAC', hash }, false, usages);","typeGuard":null,"tryCatchPattern":"try {\n  key = secretKeyObject.toCryptoKey({ name: 'HMAC', hash }, false, usages);\n} catch (e) {\n  if (e instanceof DOMException && e.name === 'SyntaxError' && e.message.includes('Usages cannot be empty')) {\n    key = secretKeyObject.toCryptoKey({ name: 'HMAC', hash }, false, ['sign']);\n  } else throw e;\n}","preventionTips":["Forbid empty usages in wrapper signatures (default to ['sign'] for HMAC)","Trace where the usages array is built; add a length assertion there","Remember every non-derivation WebCrypto key requires at least one usage"],"tags":["crypto","webcrypto","hmac","key-usage","node-compat"],"backgroundTag":"webcrypto-empty-key-usages","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}