grpc/grpc-java · error · IllegalArgumentException

'kid' parameter must not be set. Certificate loading for tru

Error message

'kid' parameter must not be set. Certificate loading for trust domain '%s' failed.

What it means

Per the SPIFFE X.509 bundle spec, JWK entries must not carry a 'kid' (key ID) parameter, since bundle keys are identified by their SPIFFE ID and x5c chain. SpiffeUtil.checkJwkEntry rejects any JWK containing 'kid' with an IllegalArgumentException naming the trust domain.

Source

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

    @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,
      String trustDomainName) {
    List<X509Certificate> result = new ArrayList<>();
    for (Map<String, ?> keyNode : keysNode) {
      checkJwkEntry(keyNode, trustDomainName);
      List<String> rawCerts = JsonUtil.getListOfStrings(keyNode, "x5c");
      if (rawCerts == null || rawCerts.isEmpty()) {
        continue;

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Remove the "kid" field from each JWK in the trust bundle file
  2. Obtain a spec-compliant bundle from your SPIRE agent instead of converting an IdP JWKS
  3. Validate bundle keys against the SPIFFE X.509 bundle format (kty, use=x509-svid, x5c; no kid)

Example fix

// before
{"kty":"RSA","use":"x509-svid","kid":"key-1","x5c":["..."]}
// after
{"kty":"RSA","use":"x509-svid","x5c":["..."]}
Defensive patterns

Strategy: validation

Validate before calling

// Strip/verify no kid fields before loading
for (Map<String, ?> key : keys) {
  if (key.containsKey("kid")) {
    throw new IllegalStateException("JWK must not contain 'kid' (SPIFFE X.509 bundle spec)");
  }
}

Type guard

boolean kidFree(Map<String, ?> jwk) {
  return !jwk.containsKey("kid");
}

Try / catch

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

Prevention

When it happens

Trigger: Loading a trust bundle whose keys include a "kid" field — commonly keys copied from a generic OIDC/OAuth JWKS endpoint where kid is standard — via extractCert during bundle loading.

Common situations: Reusing JWKS from an identity provider's /.well-known/jwks.json as a SPIFFE trust bundle; SPIFFE-compliant bundles produced by some tooling that adds kid by default.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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