grpc/grpc-java · error · IllegalArgumentException
'use' parameter must be '%s' but '%s' found. Certificate loa
Error message
'use' parameter must be '%s' but '%s' found. Certificate loading for trust domain '%s' failed.
What it means
SpiffeUtil.checkJwkEntry requires each trust bundle JWK to have 'use' set exactly to the accepted value ("x509-svid"). A missing 'use' or any other value means the key is not declared as an X.509-SVID verification key, so the check fails with an IllegalArgumentException naming the trust domain.
Source
Thrown at core/src/main/java/io/grpc/internal/SpiffeUtil.java:222
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;
}
InputStream stream = new ByteArrayInputStream((CERTIFICATE_PREFIX + rawCerts.get(0) + "\n"
+ CERTIFICATE_SUFFIX)
.getBytes(StandardCharsets.UTF_8));
try {View on GitHub (pinned to 64daddc1f3)
Solutions
- Set "use":"x509-svid" on every JWK in the trust bundle
- Use the SPIRE agent's x509 bundle endpoint output, which sets use correctly
- Do not mix JWT-SVID keys (use "jwt-svid") into an X.509 trust bundle file
Example fix
// before
{"kty":"RSA","use":"sig","x5c":["..."]}
// after
{"kty":"RSA","use":"x509-svid","x5c":["..."]} Defensive patterns
Strategy: validation
Validate before calling
// Pre-check every JWK's use field
for (Map<String, ?> key : keys) {
Object use = key.get("use");
if (!"x509-svid".equals(use)) {
throw new IllegalStateException("JWK use must be 'x509-svid', got: " + use);
}
} Type guard
boolean isX509SvidKey(Map<String, ?> jwk) {
return "x509-svid".equals(jwk.get("use"));
} Try / catch
try {
certs = SpiffeUtil.loadTrustBundleFromFile(bundlePath);
} catch (IllegalArgumentException e) {
log.error("Trust bundle JWK has wrong 'use' value: " + e.getMessage());
throw new TrustBundleLoadException(e);
} Prevention
- Separate JWT-SVID and X.509-SVID bundles; never merge their keys
- Source bundles from the SPIRE agent rather than IdP JWKS endpoints
- Schema-check bundle JWKs (kty, use=x509-svid, x5c present) in CI
When it happens
Trigger: Loading a trust bundle whose JWKs omit 'use' or use values like "sig", "jwt-svid", or "enc" instead of "x509-svid", via extractCert during trust bundle loading.
Common situations: Bundles copied from OAuth/OIDC JWKS endpoints where use is "sig"; JWT-SVID bundles mistakenly used for X.509 verification; hand-assembled bundles missing the use field.
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.
- 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
- 'kid' parameter must not be set. Certificate loading for tru
- SPIFFE Trust Bundle should be a JSON object. Found: ${type}
- Certificate can't be parsed. Certificate loading for trust d
- "key" is absent or empty
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/735fd6ce0ba81696.
Report an issue: GitHub.