grpc/grpc-java · error · IllegalArgumentException

'kty' parameter must be one of %s but '%s' found. Certificat

Error message

'kty' parameter must be one of %s but '%s' found. Certificate loading for trust domain '%s' failed.

What it means

SpiffeUtil.checkJwkEntry validates each JWK in a SPIFFE trust bundle. The 'kty' (key type) parameter must be one of the accepted values (e.g. RSA or EC); a missing or unrecognized kty makes the key unusable for X.509-SVID verification, so an IllegalArgumentException naming the trust domain is thrown.

Source

Thrown at core/src/main/java/io/grpc/internal/SpiffeUtil.java:210

    String json = new String(Files.toByteArray(file), StandardCharsets.UTF_8);
    Object jsonObject = JsonParser.parse(json);
    if (!(jsonObject instanceof Map)) {
      throw new IllegalArgumentException(
          "SPIFFE Trust Bundle should be a JSON object. Found: "
              + (jsonObject == null ? null : jsonObject.getClass()));
    }
    @SuppressWarnings("unchecked")
    Map<String, ?> root = (Map<String, ?>)jsonObject;
    Map<String, ?> trustDomainsNode = JsonUtil.getObject(root, "trust_domains");
    checkNotNull(trustDomainsNode, "Mandatory trust_domains element is missing");
    checkArgument(trustDomainsNode.size() > 0, "Mandatory trust_domains element is missing");
    return trustDomainsNode;
  }

  private static void checkJwkEntry(Map<String, ?> jwkNode, String trustDomainName) {
    String kty = JsonUtil.getString(jwkNode, "kty");
    if (kty == null || !KTY_PARAMETER_VALUES.contains(kty)) {
      throw new IllegalArgumentException(
          String.format(
              "'kty' parameter must be one of %s but '%s' "
                  + "found. Certificate loading for trust domain '%s' failed.",
              KTY_PARAMETER_VALUES, kty, trustDomainName));
    }
    if (jwkNode.containsKey("kid")) {
      throw new IllegalArgumentException(String.format("'kid' parameter must not be set. "
              + "Certificate loading for trust domain '%s' failed.", trustDomainName));
    }
    String use = JsonUtil.getString(jwkNode, "use");
    if (use == null || !use.equals(USE_PARAMETER_VALUE)) {
      throw new IllegalArgumentException(String.format("'use' parameter must be '%s' but '%s' "
              + "found. Certificate loading for trust domain '%s' failed.", USE_PARAMETER_VALUE,
          use, trustDomainName));
    }
  }

  private static List<X509Certificate> extractCert(List<Map<String, ?>> keysNode,

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Set kty to a supported value — "RSA" or "EC" — matching the actual key material
  2. Remove oct (symmetric) keys from the trust bundle; SPIFFE X.509 bundles contain only public asymmetric keys
  3. Fix casing/spelling: kty values are exact-case per RFC 7517 ("RSA", not "rsa" or "RS256")
  4. Regenerate the bundle from SPIRE (spire-agent api fetch x509-bundle) rather than hand-editing

Example fix

// before
{"use":"x509-svid","kty":"rsa","n":"..."}
// after
{"use":"x509-svid","kty":"RSA","n":"..."}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check every JWK's kty
for (Map<String, ?> key : keys) {
  String kty = (String) key.get("kty");
  if (!"RSA".equals(kty) && !"EC".equals(kty)) {
    throw new IllegalStateException("JWK kty must be RSA or EC, got: " + kty);
  }
}

Type guard

boolean hasSupportedKty(Map<String, ?> jwk) {
  Object kty = jwk.get("kty");
  return "RSA".equals(kty) || "EC".equals(kty);
}

Try / catch

try {
  certs = SpiffeUtil.loadTrustBundleFromFile(bundlePath);
} catch (IllegalArgumentException e) {
  log.error("Trust bundle JWK rejected: " + e.getMessage());
  throw new TrustBundleLoadException(e);
}

Prevention

When it happens

Trigger: Loading a trust bundle whose JWK entry lacks 'kty' or has a kty outside KTY_PARAMETER_VALUES (e.g. "oct" for symmetric keys, or a lowercase/misspelled value like "rsa"), via extractCert during bundle loading.

Common situations: Hand-built bundles with keys exported from JWKS endpoints that include oct keys; manually trimmed JWKs missing required fields; typos like "RSA " or "RS256" mistakenly placed in kty.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/b58774a3776c2c84. Report an issue: GitHub.