denoland/deno · error · DOMException
Usages cannot be empty when importing a secret key.
Error message
Usages cannot be empty when importing a secret key.
What it means
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.
Source
Thrown at ext/node/polyfills/internal/crypto/keys.ts:799
"SyntaxError",
);
}
if (
usages.length > 0 &&
ArrayPrototypeSome(
usages,
(u: string) =>
!ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
)
) {
throw new DOMException(
"Unsupported key usage for an HKDF key",
"SyntaxError",
);
}
} else if (algName === "HMAC") {
if (usages.length === 0) {
throw new DOMException(
"Usages cannot be empty when importing a secret key.",
"SyntaxError",
);
}
const alg = algorithm as { length?: number };
if (alg.length !== undefined && alg.length === 0) {
throw new DOMException(
"HmacImportParams.length cannot be 0",
"DataError",
);
}
} else if (algName === "KMAC128" || algName === "KMAC256") {
if (usages.length === 0) {
throw new DOMException(
"Usages cannot be empty when importing a secret key.",
"SyntaxError",
);
}View on GitHub (pinned to 9ad36f7a2c)
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
Example fix
// before
const key = createSecretKey(secret).toCryptoKey({ name: 'HMAC', hash: 'SHA-256' }, false, []); // throws
// after
const key = createSecretKey(secret).toCryptoKey({ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']); Defensive patterns
Strategy: validation
Validate before calling
if (usages.length === 0) {
throw new Error(`HMAC key requires usages; got none (caller: ${callerId})`);
}
const key = secretKeyObject.toCryptoKey({ name: 'HMAC', hash }, false, usages); Try / catch
try {
key = secretKeyObject.toCryptoKey({ name: 'HMAC', hash }, false, usages);
} catch (e) {
if (e instanceof DOMException && e.name === 'SyntaxError' && e.message.includes('Usages cannot be empty')) {
key = secretKeyObject.toCryptoKey({ name: 'HMAC', hash }, false, ['sign']);
} else throw e;
} Prevention
- 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
When it happens
Trigger: createSecretKey(secret).toCryptoKey({ name: 'HMAC', hash: 'SHA-256' }, false, []) — third argument is an empty array.
Common situations: 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.
Related errors
- Unsupported key usage for a PBKDF2 key
- Unsupported key usage for an HKDF key
- HmacImportParams.length cannot be 0
- Usages cannot be empty when importing a private key.
- Zero-length key is not supported
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/9d32aaa979f64605.
Report an issue: GitHub.