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
- Remove the "kid" field from each JWK in the trust bundle file
- Obtain a spec-compliant bundle from your SPIRE agent instead of converting an IdP JWKS
- 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
- Don't reuse OIDC/OAuth JWKS files as SPIFFE X.509 trust bundles
- Validate bundles against the SPIFFE X.509 bundle spec in CI
- Use spire-agent bundle output, which omits kid
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.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- 'kty' parameter must be one of %s but '%s' found. Certificat
- 'use' parameter must be '%s' but '%s' found. Certificate loa
- SPIFFE Trust Bundle should be a JSON object. Found: ${type}
- Certificate can't be parsed. Certificate loading for trust d
- Multiple URI SAN values found in the leaf cert.
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/ecf297e92a1123af.
Report an issue: GitHub.