grafana/k6 · error

invalid elliptic curve {k}

Error message

invalid elliptic curve {k}

What it means

pickEllipticCurve (internal/js/modules/k6/webcrypto/elliptic_curve.go:403) resolves the curve for ECDSA/EC operations (generateKey, importKey, signing) and, like its ECDH counterpart, accepts only 'P-256', 'P-384' and 'P-521'. Anything else — including case variants and other curve families — returns "invalid elliptic curve <k>" with the offending name appended.

Source

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

	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 {
		return nil, NewError(OperationError, "key data is not accessible")
	}

	alg, ok := ck.Algorithm.(EcKeyAlgorithm)
	if !ok {
		return nil, NewError(InvalidAccessError, "key algorithm is not a valid EC algorithm")
	}

	switch format {
	case RawKeyFormat:
		if ck.Type != PublicCryptoKeyType {
			return nil, NewError(InvalidAccessError, "key is not a valid elliptic curve public key")
		}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Use exactly 'P-256', 'P-384', or 'P-521' as namedCurve
  2. Check for typos, casing and the dash in the curve string
  3. For non-NIST curves, k6's webcrypto cannot generate/sign — precompute keys or offload the operation

Example fix

// before
const key = await crypto.subtle.generateKey(
  { name: 'ECDSA', namedCurve: 'secp256k1', hash: 'SHA-256' }, true, ['sign', 'verify']);

// after
const key = await crypto.subtle.generateKey(
  { name: 'ECDSA', namedCurve: 'P-256', hash: 'SHA-256' }, true, ['sign', 'verify']);
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_EC_CURVES = ['P-256', 'P-384', 'P-521'];
if (!SUPPORTED_EC_CURVES.includes(alg.namedCurve)) {
  throw new Error(`unsupported EC curve ${alg.namedCurve}`);
}

Type guard

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

Try / catch

try {
  key = await crypto.subtle.generateKey({ name: 'ECDSA', namedCurve, hash: { name: 'SHA-256' } }, true, ['sign', 'verify']);
} catch (e) {
  if (String(e.message).includes('invalid elliptic curve')) throw new Error(`namedCurve '${namedCurve}' unsupported/misspelled; use P-256/P-384/P-521`);
  throw e;
}

Prevention

When it happens

Trigger: `crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'secp256k1', hash: 'SHA-256' }, ...)`; namedCurve 'p-256' (lowercase) or 'P256' (missing dash); importing a JWK EC key with an unsupported crv value.

Common situations: Blockchain/secp256k1-related signing code ported into load tests; curve names copied from other libraries (Node crypto, jose) that use different spellings; case-sensitive copy-paste errors.

Related errors


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