grafana/k6 · error
failed to convert ECDH key to ECDSA key: %w
Error message
failed to convert ECDH key to ECDSA key: %w
What it means
k6's WebCrypto implementation stores ECDH keys internally as Go *ecdh.PrivateKey handles, but the JWK exporter (exportECJWK in internal/js/modules/k6/webcrypto/jwk.go) only serializes ECDSA-shaped keys, so it first converts the ECDH key via convertECDHtoECDSAKey. This error means that conversion failed, and it is raised from crypto.subtle.exportKey('jwk', key). The underlying cause is either an unsupported curve (only P-256/P-384/P-521 map to ECDSA curves) or a public point that cannot be unmarshaled onto the ECDSA curve.
Source
Thrown at internal/js/modules/k6/webcrypto/jwk.go:188
exported.Set("kty", JWKECKeyType)
var x, y, d *big.Int
var curveParams *elliptic.CurveParams
switch k := key.handle.(type) {
case *ecdsa.PrivateKey:
x = k.X
y = k.Y
d = k.D
curveParams = k.Params()
case *ecdsa.PublicKey:
x = k.X
y = k.Y
curveParams = k.Params()
case *ecdh.PrivateKey:
ecdsaKey, err := convertECDHtoECDSAKey(k)
if err != nil {
return nil, fmt.Errorf("failed to convert ECDH key to ECDSA key: %w", err)
}
x = ecdsaKey.X
y = ecdsaKey.Y
d = ecdsaKey.D
curveParams = ecdsaKey.Params()
case *ecdh.PublicKey:
ecdsaKey, err := convertPublicECDHtoECDSA(k)
if err != nil {
return nil, fmt.Errorf("failed to convert ECDH key to ECDSA key: %w", err)
}
x = ecdsaKey.X
y = ecdsaKey.Y
curveParams = ecdsaKey.Params()
default:
return nil, errors.New("key's handle isn't an ECDSA/ECDH public/private key")
}View on GitHub (pinned to 93accf6570)
Solutions
- Confirm the key was generated/imported with namedCurve 'P-256', 'P-384' or 'P-521'
- Re-generate the key pair with crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-256'}, ...) and export the new key
- Fall back to exporting in 'raw' (public), 'spki' (public) or 'pkcs8' (private) format, which do not use the ECDSA conversion
- If the key came from generateKey with a supported curve, report it as a k6 bug at https://github.com/grafana/k6/issues including the curve and import path used
Example fix
// before
const jwk = await crypto.subtle.exportKey('jwk', ecdhPrivKey); // throws: failed to convert ECDH key to ECDSA key
// after
const raw = new Uint8Array(await crypto.subtle.exportKey('pkcs8', ecdhPrivKey));
// or regenerate with a supported curve:
const pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveKey', 'deriveBits']);
const jwk2 = await crypto.subtle.exportKey('jwk', pair.privateKey); Defensive patterns
Strategy: try-catch
Validate before calling
const SUPPORTED = ['P-256', 'P-384', 'P-521'];
function canExportEcdhJwk(key) {
return key.algorithm && key.algorithm.name === 'ECDH' &&
SUPPORTED.includes(key.algorithm.namedCurve);
} Type guard
function isExportableEcdhKey(key) {
return key && key.algorithm && key.algorithm.name === 'ECDH' &&
['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve) &&
typeof key.extract === 'function';
} Try / catch
try {
const jwk = await crypto.subtle.exportKey('jwk', ecdhPriv);
} catch (e) {
if (e.message.includes('failed to convert ECDH key to ECDSA key')) {
const pkcs8 = await crypto.subtle.exportKey('pkcs8', ecdhPriv); // fallback format
} else { throw e; }
} Prevention
- Generate ECDH keys only with namedCurve P-256/P-384/P-521
- Set extractable=true at generateKey/importKey time if you plan to export as JWK
- Round-trip test: export a freshly generated key as Jwk once in a sanity check
When it happens
Trigger: Calling crypto.subtle.exportKey('jwk', ecdhPrivateKey) where the key handle's curve is not P-256, P-384 or P-521, or where the stored key bytes are not a valid point on the curve (corrupted handle). The error is wrapped around the converter's own error ('curve not supported for converting to ECDSA key' or 'unable to convert ECDH public key to ECDSA public key').
Common situations: Exporting an ECDH key that was generated or imported outside the supported NIST curves; keys whose material was mutated between import and export; edge-case k6 versions where the ECDH handle was constructed inconsistently. Rare in practice because import paths validate the point, so hitting it usually indicates an internal inconsistency.
Related errors
- failed to convert ECDSA key to ECDH key: %w
- curve not supported for converting to ECDSA key
- unable to convert ECDH public key to ECDSA public key, curve
- failed to parse elliptic curve: %w
- failed to parse input as ECDH key: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/8df931a744473bab.
Report an issue: GitHub.