{"record":{"id":"8bea7e15b4f9175e","repo":"VictoriaMetrics/VictoriaMetrics","slug":"failed-to-decode-jwks-key-n-w","errorCode":null,"errorMessage":"failed to decode jwks key n: %w","messagePattern":"failed to decode jwks key n: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/jwt/jwks.go","lineNumber":73,"sourceCode":"\t\t\tcontinue\n\t\t}\n\t\tswitch key.Kty {\n\t\tcase \"RSA\":\n\t\t\tif key.E == \"\" || key.N == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"jwks key without e or n found\")\n\t\t\t}\n\t\t\te, err := base64.RawURLEncoding.DecodeString(key.E)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to decode jwks key e: %w\", err)\n\t\t\t}\n\t\t\texp := big.NewInt(0).SetBytes(e)\n\t\t\tif !exp.IsInt64() || exp.Int64() < 1 {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid RSA exponent\")\n\t\t\t}\n\n\t\t\tn, err := base64.RawURLEncoding.DecodeString(key.N)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to decode jwks key n: %w\", err)\n\t\t\t}\n\n\t\t\tk := &rsa.PublicKey{\n\t\t\t\tE: int(exp.Int64()),\n\t\t\t\tN: big.NewInt(0).SetBytes(n),\n\t\t\t}\n\n\t\t\tif slices.Contains(rsaAlgs, key.Alg) {\n\t\t\t\tv, err := newVerifierRS(Algorithm(key.Alg), k)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"failed to create RSA verifier for algorithm %s: %w\", key.Alg, err)\n\t\t\t\t}\n\t\t\t\tvs = append(vs, &verifier{\n\t\t\t\t\tVerifier: v,\n\n\t\t\t\t\tkey: k,\n\t\t\t\t\talg: key.Alg,\n\t\t\t\t\tkid: key.Kid,","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/jwt/jwks.go#L55-L91","documentation":"ParseJWKs base64url-decodes the RSA modulus 'n'; if 'n' is not valid unpadded base64url the JWKS parse fails entirely. The modulus is the core of the RSA public key, so a bad 'n' means the key is unusable for verification.","triggerScenarios":"A JWKS RSA key with 'n' containing '+' or '/', '=' padding, whitespace, or other characters rejected by base64.RawURLEncoding.DecodeString.","commonSituations":"Standard base64 used instead of base64url when generating fixture keys; line-wrapped PEM data pasted into 'n'; IdP or proxy mangling the JWKS JSON.","solutions":["Re-encode the modulus with base64.RawURLEncoding (no padding, URL-safe alphabet)","Confirm the value is the raw modulus bytes, not a PEM or hex string","Decode it locally with base64.RawURLEncoding.DecodeString to see the exact failing character","Fetch a fresh JWKS from the IdP's well-known endpoint"],"exampleFix":"// Go: fix encoding when generating the key\n// before: base64.StdEncoding.EncodeToString(n)\n// after\nbase64.RawURLEncoding.EncodeToString(n)","handlingStrategy":"validation","validationCode":"if _, err := base64.RawURLEncoding.DecodeString(jwk.N); err != nil {\n    return fmt.Errorf(\"jwk %s: invalid n field: %w\", jwk.Kid, err)\n}","typeGuard":"func validB64URL(s string) bool {\n    _, err := base64.RawURLEncoding.DecodeString(s)\n    return err == nil\n}","tryCatchPattern":"keys, err := ParseJWKs(raw)\nif err != nil {\n    var decErr error\n    if strings.Contains(err.Error(), \"failed to decode jwks key n\") { decErr = err }\n    if decErr != nil { logger.Errorf(\"bad modulus in JWKS: %v\", decErr) }\n    return err\n}","preventionTips":["Encode moduli with base64.RawURLEncoding, never StdEncoding","Verify JWKS JSON isn't line-wrapped or re-encoded by proxies","Re-fetch from the IdP's /.well-known/jwks.json when in doubt","Add a JWKS fixture validation unit test"],"tags":["jwt","jwks","base64","rsa"],"backgroundTag":"jwks-key-parse-failed","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}