denoland/deno · error · ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

Error message

The argument 'type' must be a supported key type. Received ${type}

What it means

crypto.generateKey and generateKeySync only create symmetric secret keys, so their option validator (ext/node/polyfills/internal/crypto/keygen.ts:81-95) accepts exactly type 'hmac' (integer length 8..2^31-1) or 'aes' (length one of 128/192/256). Any other type string falls into the default branch and throws ERR_INVALID_ARG_VALUE with 'must be a supported key type'.

Source

Thrown at ext/node/polyfills/internal/crypto/keygen.ts:89

  op_node_get_public_key_from_pair,
} = core.ops;

function validateGenerateKey(
  type: "hmac" | "aes",
  options: { length: number },
) {
  validateString(type, "type");
  validateObject(options, "options");
  const { length } = options;
  switch (type) {
    case "hmac":
      validateInteger(length, "options.length", 8, 2 ** 31 - 1);
      break;
    case "aes":
      validateOneOf(length, "options.length", kAesKeyLengths);
      break;
    default:
      throw new ERR_INVALID_ARG_VALUE(
        "type",
        type,
        "must be a supported key type",
      );
  }
}

function generateKeySync(
  type: "hmac" | "aes",
  options: {
    length: number;
  },
): KeyObject {
  validateGenerateKey(type, options);
  const { length } = options;

  const len = Math.floor(length / 8);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use crypto.generateKeyPair[Sync] for asymmetric keys (rsa, ec, ed25519, dh...).
  2. Use generateKey('hmac', { length: 256 }) or generateKey('aes', { length: 128|192|256 }) for symmetric secrets.
  3. Validate the type against ['hmac','aes'] before calling when it comes from config or user input.

Example fix

// before
crypto.generateKeySync('rsa', { length: 2048 }); // ERR_INVALID_ARG_VALUE: unsupported type

// after
const hmacKey = crypto.generateKeySync('hmac', { length: 256 });
const aesKey = crypto.generateKeySync('aes', { length: 256 });
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
});
Defensive patterns

Strategy: validation

Validate before calling

const SECRET_TYPES = new Set(['hmac', 'aes']);
function generateSecret(type, options) {
  if (!SECRET_TYPES.has(type)) {
    throw new Error(`generateKey supports ${[...SECRET_TYPES]}; use generateKeyPair for '${type}'`);
  }
  return crypto.generateKeySync(type, options);
}

Type guard

function isSecretKeyType(t) {
  return t === 'hmac' || t === 'aes';
}

Try / catch

try {
  key = crypto.generateKeySync(type, opts);
} catch (e) {
  if (e.code === 'ERR_INVALID_ARG_VALUE' && /type/.test(e.message)) {
    ({ publicKey, privateKey } = crypto.generateKeyPairSync(type, pairOpts(type)));
  } else throw e;
}

Prevention

When it happens

Trigger: crypto.generateKeySync('rsa', { length: 2048 }); generateKeySync('ed25519', {...}); generateKeySync('aes', { length: 100 }); generateKey('hmac', { length: 4 }) throws a validateInteger error instead - the type throw is specifically for names outside {hmac, aes}.

Common situations: Assuming generateKey is a general-purpose generator and trying to make RSA/EC/Ed25519 keys with it; migrating from WebCrypto generateKey (which does handle asymmetric types) to node:crypto; JSON configs driving the 'type' field.

Related errors


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