{"record":{"id":"f6cb634d9794fadd","repo":"grafana/k6","slug":"failed-to-decode-x-coordinate-w","errorCode":null,"errorMessage":"failed to decode X coordinate: %w","messagePattern":"failed to decode X coordinate: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/webcrypto/jwk.go","lineNumber":238,"sourceCode":"\nfunc importECDSAJWK(_ EllipticCurveKind, jsonKeyData []byte) (any, CryptoKeyType, error) {\n\tvar jwkKey ecJWK\n\tif err := json.Unmarshal(jsonKeyData, &jwkKey); err != nil {\n\t\treturn nil, UnknownCryptoKeyType, fmt.Errorf(\"failed to parse input as EC JWK key: %w\", err)\n\t}\n\n\tif err := jwkKey.validate(); err != nil {\n\t\treturn nil, UnknownCryptoKeyType, fmt.Errorf(\"invalid EC JWK key: %w\", err)\n\t}\n\n\tcrv, err := pickEllipticCurve(jwkKey.Crv)\n\tif err != nil {\n\t\treturn nil, UnknownCryptoKeyType, fmt.Errorf(\"failed to parse elliptic curve: %w\", err)\n\t}\n\n\tx, err := base64URLDecode(jwkKey.X)\n\tif err != nil {\n\t\treturn nil, UnknownCryptoKeyType, fmt.Errorf(\"failed to decode X coordinate: %w\", err)\n\t}\n\n\ty, err := base64URLDecode(jwkKey.Y)\n\tif err != nil {\n\t\treturn nil, UnknownCryptoKeyType, fmt.Errorf(\"failed to decode Y coordinate: %w\", err)\n\t}\n\n\tpk := &ecdsa.PublicKey{\n\t\tCurve: crv,\n\t\tX:     new(big.Int).SetBytes(x),\n\t\tY:     new(big.Int).SetBytes(y),\n\t}\n\n\t// if the key is a public key, return it\n\tif jwkKey.D == \"\" {\n\t\treturn pk, PublicCryptoKeyType, nil\n\t}\n","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/webcrypto/jwk.go#L220-L256","documentation":"The x coordinate is decoded with base64.RawURLEncoding (base64url without padding). This error means the x string is not valid unpadded base64url: it contains '=', '+' or '/' characters, whitespace, or its length is impossible (length % 4 == 1). It is raised from crypto.subtle.importKey('jwk', ...) for ECDSA keys.","triggerScenarios":"x encoded in standard base64 ('+/' alphabet) or padded base64url (trailing '='); x with trailing whitespace or newline from copy-paste; truncated x.","commonSituations":"JWKs produced by toolchains that emit padded or standard base64; coordinates copied from PEM/ASN.1 dumps; strings trimmed incorrectly during transport (JSON escaping issues).","solutions":["Convert x to unpadded base64url: replace '+' with '-', '/' with '_', and strip trailing '=' characters","Re-encode the coordinate from the original raw bytes using base64url without padding","Check for and remove whitespace/newlines inside the value","Verify the decoded byte length matches the curve (32 bytes for P-256, 48 for P-384, 66 for P-521)"],"exampleFix":"// before\nconst jwk = { kty: 'EC', crv: 'P-256', x: b64X, y: b64Y }; // padded/standard base64\n// after\nconst toB64u = (s) => s.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '').trim();\nconst jwk = { kty: 'EC', crv: 'P-256', x: toB64u(b64X), y: toB64u(b64Y) };","handlingStrategy":"validation","validationCode":"const B64URL = /^[A-Za-z0-9_-]+$/;\nconst toB64u = (s) => String(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '').trim();\nconst x = toB64u(jwk.x);\nif (!B64URL.test(x) || x.length < 2) throw new Error('x is not valid unpadded base64url');","typeGuard":"function isB64uCoord(s) {\n  return typeof s === 'string' && /^[A-Za-z0-9_-]+$/.test(s) && s.length % 4 !== 1;\n}","tryCatchPattern":"try {\n  key = await crypto.subtle.importKey('jwk', jwk, alg, true, usages);\n} catch (e) {\n  if (e.message.includes('failed to decode X coordinate')) {\n    jwk = { ...jwk, x: toB64u(jwk.x), y: toB64u(jwk.y) };\n    key = await crypto.subtle.importKey('jwk', jwk, alg, true, usages);\n  } else throw e;\n}","preventionTips":["Normalize all JWK fields to unpadded base64url at load time","Expect 43 chars for P-256 x, 64 for P-384, 88 for P-521","Never paste coordinates with '=' padding or '+'/'/' characters"],"tags":["webcrypto","jwk","import","ecdsa","base64url","k6"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}