grafana/k6 · error

invalid ECDH curve

Error message

invalid ECDH curve

What it means

pickECDHCurve (internal/js/modules/k6/webcrypto/elliptic_curve.go:391) maps the namedCurve string of an ECDH operation to a Go ecdh.Curve. Only the NIST curves 'P-256', 'P-384' and 'P-521' (their canonical spellings) are supported; any other value falls through to "invalid ECDH curve". It is used when generating, importing, or deriving with ECDH keys.

Source

Thrown at internal/js/modules/k6/webcrypto/elliptic_curve.go:399

	return rawPrivateKey, &rawPrivateKey.PublicKey, nil
}

// isValidEllipticCurve returns true if the given elliptic curve is supported,
func isValidEllipticCurve(curve EllipticCurveKind) bool {
	return curve == EllipticCurveKindP256 || curve == EllipticCurveKindP384 || curve == EllipticCurveKindP521
}

func pickECDHCurve(k string) (ecdh.Curve, error) {
	switch k {
	case p256Canonical:
		return ecdh.P256(), nil
	case p384Canonical:
		return ecdh.P384(), nil
	case p521Canonical:
		return ecdh.P521(), nil
	default:
		return nil, errors.New("invalid ECDH curve")
	}
}

func pickEllipticCurve(k string) (elliptic.Curve, error) {
	switch k {
	case p256Canonical:
		return elliptic.P256(), nil
	case p384Canonical:
		return elliptic.P384(), nil
	case p521Canonical:
		return elliptic.P521(), nil
	default:
		return nil, errors.New("invalid elliptic curve " + k)
	}
}

func exportECKey(ck *CryptoKey, format KeyFormat) (any, error) {
	if ck.handle == nil {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Use one of the supported curves: 'P-256', 'P-384', or 'P-521'
  2. Fix casing/spelling — the canonical form is uppercase 'P-XXX'
  3. If you need X25519-style curves, do the ECDH outside k6 (e.g. against a service) since webcrypto in k6 only supports NIST curves

Example fix

// before
const pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'X25519' }, true, ['deriveKey']);

// after
const pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveKey']);
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_ECDH_CURVES = ['P-256', 'P-384', 'P-521'];
if (!SUPPORTED_ECDH_CURVES.includes(namedCurve)) {
  throw new Error(`unsupported ECDH curve ${namedCurve}; use one of ${SUPPORTED_ECDH_CURVES.join(', ')}`);
}

Type guard

const isSupportedCurve = (c) => ['P-256', 'P-384', 'P-521'].includes(c);

Try / catch

try {
  pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve }, true, ['deriveBits']);
} catch (e) {
  if (String(e.message).includes('invalid ECDH curve')) throw new Error(`curve '${namedCurve}' not supported; use P-256/P-384/P-521`);
  throw e;
}

Prevention

When it happens

Trigger: `crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'X25519' }, ...)` or namedCurve values like 'secp256k1', 'P-256K', 'p-256', 'Ed25519'; also importing a JWK ECDH key whose crv is not one of the three supported curves.

Common situations: Porting crypto code from Node.js/browsers that support X25519; typos or wrong case in the curve name; interoperating with systems that default to non-NIST curves.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/4d77c6cb2157d288. Report an issue: GitHub.