VictoriaMetrics/VictoriaMetrics · error

failed to decode jwks key n: %w

Error message

failed to decode jwks key n: %w

What it means

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.

Source

Thrown at lib/jwt/jwks.go:73

			continue
		}
		switch key.Kty {
		case "RSA":
			if key.E == "" || key.N == "" {
				return nil, fmt.Errorf("jwks key without e or n found")
			}
			e, err := base64.RawURLEncoding.DecodeString(key.E)
			if err != nil {
				return nil, fmt.Errorf("failed to decode jwks key e: %w", err)
			}
			exp := big.NewInt(0).SetBytes(e)
			if !exp.IsInt64() || exp.Int64() < 1 {
				return nil, fmt.Errorf("invalid RSA exponent")
			}

			n, err := base64.RawURLEncoding.DecodeString(key.N)
			if err != nil {
				return nil, fmt.Errorf("failed to decode jwks key n: %w", err)
			}

			k := &rsa.PublicKey{
				E: int(exp.Int64()),
				N: big.NewInt(0).SetBytes(n),
			}

			if slices.Contains(rsaAlgs, key.Alg) {
				v, err := newVerifierRS(Algorithm(key.Alg), k)
				if err != nil {
					return nil, fmt.Errorf("failed to create RSA verifier for algorithm %s: %w", key.Alg, err)
				}
				vs = append(vs, &verifier{
					Verifier: v,

					key: k,
					alg: key.Alg,
					kid: key.Kid,

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Re-encode the modulus with base64.RawURLEncoding (no padding, URL-safe alphabet)
  2. Confirm the value is the raw modulus bytes, not a PEM or hex string
  3. Decode it locally with base64.RawURLEncoding.DecodeString to see the exact failing character
  4. Fetch a fresh JWKS from the IdP's well-known endpoint

Example fix

// Go: fix encoding when generating the key
// before: base64.StdEncoding.EncodeToString(n)
// after
base64.RawURLEncoding.EncodeToString(n)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := base64.RawURLEncoding.DecodeString(jwk.N); err != nil {
    return fmt.Errorf("jwk %s: invalid n field: %w", jwk.Kid, err)
}

Type guard

func validB64URL(s string) bool {
    _, err := base64.RawURLEncoding.DecodeString(s)
    return err == nil
}

Try / catch

keys, err := ParseJWKs(raw)
if err != nil {
    var decErr error
    if strings.Contains(err.Error(), "failed to decode jwks key n") { decErr = err }
    if decErr != nil { logger.Errorf("bad modulus in JWKS: %v", decErr) }
    return err
}

Prevention

When it happens

Trigger: A JWKS RSA key with 'n' containing '+' or '/', '=' padding, whitespace, or other characters rejected by base64.RawURLEncoding.DecodeString.

Common situations: Standard base64 used instead of base64url when generating fixture keys; line-wrapped PEM data pasted into 'n'; IdP or proxy mangling the JWKS JSON.

Understand the failure class

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/8bea7e15b4f9175e. Report an issue: GitHub.