grafana/k6 · error
failed to parse input as EC JWK key: %w
Error message
failed to parse input as EC JWK key: %w
What it means
importECDSAJWK first unmarshals the JWK bytes into the internal ecJWK struct; this error means that JSON unmarshaling failed. In k6 the JWK is passed as a JavaScript object which is re-serialized with json.Marshal, so a valid object almost never fails here — the failure comes from fields having the wrong JSON type (ecJWK expects kty/crv/x/y/d to be strings). The wrapped %w carries Go's precise 'json: cannot unmarshal ...' message.
Source
Thrown at internal/js/modules/k6/webcrypto/jwk.go:224
}
exported.Set("crv", curveParams.Name)
curveBits := curveParams.BitSize
exported.Set("x", base64URLEncode(x.Bytes()))
exported.Set("y", base64URLEncode(y.Bytes()))
if d != nil {
exported.Set("d", encodeCurveBigInt(d, curveBits))
}
return exported, nil
}
func importECDSAJWK(_ EllipticCurveKind, jsonKeyData []byte) (any, CryptoKeyType, error) {
var jwkKey ecJWK
if err := json.Unmarshal(jsonKeyData, &jwkKey); err != nil {
return nil, UnknownCryptoKeyType, fmt.Errorf("failed to parse input as EC JWK key: %w", err)
}
if err := jwkKey.validate(); err != nil {
return nil, UnknownCryptoKeyType, fmt.Errorf("invalid EC JWK key: %w", err)
}
crv, err := pickEllipticCurve(jwkKey.Crv)
if err != nil {
return nil, UnknownCryptoKeyType, fmt.Errorf("failed to parse elliptic curve: %w", err)
}
x, err := base64URLDecode(jwkKey.X)
if err != nil {
return nil, UnknownCryptoKeyType, fmt.Errorf("failed to decode X coordinate: %w", err)
}
y, err := base64URLDecode(jwkKey.Y)
if err != nil {View on GitHub (pinned to 93accf6570)
Solutions
- Pass a plain JavaScript object as keyData, not a JSON string
- Ensure kty, crv, x, y and d are all strings
- If the JWK arrives as text, JSON.parse it before calling importKey
- Log the wrapped cause after 'failed to parse input as EC JWK key:' to identify the offending field
Example fix
// before
const key = await crypto.subtle.importKey('jwk', JSON.stringify(jwk), alg, true, ['verify']);
// after
const key = await crypto.subtle.importKey('jwk', jwk, alg, true, ['verify']); Defensive patterns
Strategy: validation
Validate before calling
function isPlainObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }
function looksLikeEcJwk(v) {
return isPlainObject(v) && ['kty','crv','x','y'].every(f => v[f] === undefined || typeof v[f] === 'string');
}
// before import:
if (!looksLikeEcJwk(jwk)) throw new Error('pass a JWK object with string fields, not JSON text'); Type guard
function isEcJwkShape(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v) &&
Object.entries(v).every(([k, val]) =>
['kty','crv','x','y','d'].includes(k) ? typeof val === 'string' : true);
} Try / catch
try {
key = await crypto.subtle.importKey('jwk', jwk, alg, true, usages);
} catch (e) {
if (e.message.includes('failed to parse input as EC JWK key')) {
throw new Error('JWK must be a plain object with string fields (got: ' + e.message + ')');
}
throw e;
} Prevention
- Always pass the parsed object to importKey; never JSON.stringify it first
- If reading from a file/env var, JSON.parse once at load time
- Treat any non-string kty/crv/x/y/d as a build error in fixtures
When it happens
Trigger: crypto.subtle.importKey('jwk', keyData, {name:'ECDSA', namedCurve:...}, ...) where keyData is a JSON string instead of an object (double encoding makes the top level a string), or where x/y/crv/d are numbers/arrays/objects instead of strings, or where keyData is an array.
Common situations: Passing JSON.stringify-ed JWKs into importKey (habit from Node's crypto where raw strings are used); JWKs from external services that emit coordinates as byte arrays; script authors building JWKs programmatically with numeric fields.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid EC JWK key: %w
- failed to parse elliptic curve: %w
- failed to decode X coordinate: %w
- failed to decode Y coordinate: %w
- failed to decode D: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/8839862c397f31e1.
Report an issue: GitHub.