{"record":{"id":"4d77c6cb2157d288","repo":"grafana/k6","slug":"invalid-ecdh-curve","errorCode":null,"errorMessage":"invalid ECDH curve","messagePattern":"invalid ECDH curve","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/webcrypto/elliptic_curve.go","lineNumber":399,"sourceCode":"\n\treturn rawPrivateKey, &rawPrivateKey.PublicKey, nil\n}\n\n// isValidEllipticCurve returns true if the given elliptic curve is supported,\nfunc isValidEllipticCurve(curve EllipticCurveKind) bool {\n\treturn curve == EllipticCurveKindP256 || curve == EllipticCurveKindP384 || curve == EllipticCurveKindP521\n}\n\nfunc pickECDHCurve(k string) (ecdh.Curve, error) {\n\tswitch k {\n\tcase p256Canonical:\n\t\treturn ecdh.P256(), nil\n\tcase p384Canonical:\n\t\treturn ecdh.P384(), nil\n\tcase p521Canonical:\n\t\treturn ecdh.P521(), nil\n\tdefault:\n\t\treturn nil, errors.New(\"invalid ECDH curve\")\n\t}\n}\n\nfunc pickEllipticCurve(k string) (elliptic.Curve, error) {\n\tswitch k {\n\tcase p256Canonical:\n\t\treturn elliptic.P256(), nil\n\tcase p384Canonical:\n\t\treturn elliptic.P384(), nil\n\tcase p521Canonical:\n\t\treturn elliptic.P521(), nil\n\tdefault:\n\t\treturn nil, errors.New(\"invalid elliptic curve \" + k)\n\t}\n}\n\nfunc exportECKey(ck *CryptoKey, format KeyFormat) (any, error) {\n\tif ck.handle == nil {","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/webcrypto/elliptic_curve.go#L381-L417","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Use one of the supported curves: 'P-256', 'P-384', or 'P-521'","Fix casing/spelling — the canonical form is uppercase 'P-XXX'","If you need X25519-style curves, do the ECDH outside k6 (e.g. against a service) since webcrypto in k6 only supports NIST curves"],"exampleFix":"// before\nconst pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'X25519' }, true, ['deriveKey']);\n\n// after\nconst pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveKey']);","handlingStrategy":"validation","validationCode":"const SUPPORTED_ECDH_CURVES = ['P-256', 'P-384', 'P-521'];\nif (!SUPPORTED_ECDH_CURVES.includes(namedCurve)) {\n  throw new Error(`unsupported ECDH curve ${namedCurve}; use one of ${SUPPORTED_ECDH_CURVES.join(', ')}`);\n}","typeGuard":"const isSupportedCurve = (c) => ['P-256', 'P-384', 'P-521'].includes(c);","tryCatchPattern":"try {\n  pair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve }, true, ['deriveBits']);\n} catch (e) {\n  if (String(e.message).includes('invalid ECDH curve')) throw new Error(`curve '${namedCurve}' not supported; use P-256/P-384/P-521`);\n  throw e;\n}","preventionTips":["Define the curve once as a constant ('P-256') and reuse it everywhere","Spell curves exactly as P-256/P-384/P-521 — matching case and dash","Check peer systems' curve before porting ECDH code from Node/browsers"],"tags":["webcrypto","ecdh","elliptic-curve","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}