denoland/deno · error · TypeError

Invalid EC curve name

Error message

Invalid EC curve name

What it means

A TypeError thrown by ECDH.convertKey() when the native op_node_ecdh_encode_pubkey op rejects the curve name with 'Unsupported curve'. Unlike the ECDH constructor (which validates against a JS curve table), convertKey only checks that curve is a string, then hands it straight to the crypto backend; if the backend has no implementation for that curve you get this error instead of the constructor's 'invalid curve'.

Source

Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:1420

        compress = false;
      } else {
        throw new ERR_CRYPTO_ECDH_INVALID_FORMAT(format);
      }
    } else {
      compress = false;
    }

    let result;
    try {
      result = Buffer.from(
        op_node_ecdh_encode_pubkey(curve, buf, compress),
      );
    } catch (e) {
      if (
        ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e) &&
        (e as Error).message === "Unsupported curve"
      ) {
        throw new TypeError("Invalid EC curve name");
      }
      throw new Error("Failed to convert Buffer to EC_POINT");
    }

    if (format === "hybrid") {
      // Hybrid format: same as uncompressed but first byte is 06 or 07
      // Get compressed form to determine parity
      const compressedBuf = Buffer.from(
        op_node_ecdh_encode_pubkey(curve, buf, true),
      );
      // compressed first byte is 02 (even) or 03 (odd)
      // hybrid first byte is 06 (even) or 07 (odd)
      result[0] = compressedBuf[0] + 4;
    }

    if (outputEncoding && outputEncoding !== "buffer") {
      // deno-lint-ignore deno-internal/prefer-primordials -- Buffer.prototype.toString(encoding) has no primordial
      return result.toString(outputEncoding);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use a curve the backend implements: 'prime256v1' (secp256r1), 'secp384r1', 'secp521r1', or 'X25519'
  2. Print/inspect the exact curve string for typos or stray whitespace before the call
  3. If you truly need an unsupported curve, generate the key material with another tool and pass raw buffers, or pick a supported equivalent curve and re-key

Example fix

// before
const out = crypto.ECDH.convertKey(key, 'brainpoolP256r1');

// after
const out = crypto.ECDH.convertKey(key, 'prime256v1');
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = new Set(['prime256v1', 'secp256r1', 'secp384r1', 'secp521r1', 'X25519']);
if (!SUPPORTED.has(curve)) {
  throw new RangeError(`unsupported curve '${curve}'; supported: ${[...SUPPORTED].join(', ')}`);
}
const out = crypto.ECDH.convertKey(key, curve, inputEncoding, outputEncoding, format);

Try / catch

catch (e) { if (e instanceof TypeError && e.message === 'Invalid EC curve name') { /* surface a config error pointing at the curve name */ } throw e; }

Prevention

When it happens

Trigger: ECDH.convertKey(key, 'brainpoolP256r1') or any curve name the native layer does not implement (e.g. brainpool, made-up names, or a typo like 'secp256r1x'), even though the string passes validateString.

Common situations: Migrating code from OpenSSL or BouncyCastle that uses brainpool or other exotic curves; typos in curve names; scripts that worked on Node builds with fuller OpenSSL curve support and are re-run under a runtime with a smaller curve set.

Related errors


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