{"record":{"id":"735fd6ce0ba81696","repo":"grpc/grpc-java","slug":"use-parameter-must-be-s-but-s-found-certi","errorCode":null,"errorMessage":"'use' parameter must be '%s' but '%s' found. Certificate loading for trust domain '%s' failed.","messagePattern":"'use' parameter must be '(.+?)' but '(.+?)' found\\. Certificate loading for trust domain '(.+?)' failed\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/grpc/internal/SpiffeUtil.java","lineNumber":222,"sourceCode":"    return trustDomainsNode;\n  }\n\n  private static void checkJwkEntry(Map<String, ?> jwkNode, String trustDomainName) {\n    String kty = JsonUtil.getString(jwkNode, \"kty\");\n    if (kty == null || !KTY_PARAMETER_VALUES.contains(kty)) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"'kty' parameter must be one of %s but '%s' \"\n                  + \"found. Certificate loading for trust domain '%s' failed.\",\n              KTY_PARAMETER_VALUES, kty, trustDomainName));\n    }\n    if (jwkNode.containsKey(\"kid\")) {\n      throw new IllegalArgumentException(String.format(\"'kid' parameter must not be set. \"\n              + \"Certificate loading for trust domain '%s' failed.\", trustDomainName));\n    }\n    String use = JsonUtil.getString(jwkNode, \"use\");\n    if (use == null || !use.equals(USE_PARAMETER_VALUE)) {\n      throw new IllegalArgumentException(String.format(\"'use' parameter must be '%s' but '%s' \"\n              + \"found. Certificate loading for trust domain '%s' failed.\", USE_PARAMETER_VALUE,\n          use, trustDomainName));\n    }\n  }\n\n  private static List<X509Certificate> extractCert(List<Map<String, ?>> keysNode,\n      String trustDomainName) {\n    List<X509Certificate> result = new ArrayList<>();\n    for (Map<String, ?> keyNode : keysNode) {\n      checkJwkEntry(keyNode, trustDomainName);\n      List<String> rawCerts = JsonUtil.getListOfStrings(keyNode, \"x5c\");\n      if (rawCerts == null || rawCerts.isEmpty()) {\n        continue;\n      }\n      InputStream stream = new ByteArrayInputStream((CERTIFICATE_PREFIX + rawCerts.get(0) + \"\\n\"\n          + CERTIFICATE_SUFFIX)\n          .getBytes(StandardCharsets.UTF_8));\n      try {","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/SpiffeUtil.java#L204-L240","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n{\"kty\":\"RSA\",\"use\":\"sig\",\"x5c\":[\"...\"]}\n// after\n{\"kty\":\"RSA\",\"use\":\"x509-svid\",\"x5c\":[\"...\"]}","handlingStrategy":"validation","validationCode":"// Pre-check every JWK's use field\nfor (Map<String, ?> key : keys) {\n  Object use = key.get(\"use\");\n  if (!\"x509-svid\".equals(use)) {\n    throw new IllegalStateException(\"JWK use must be 'x509-svid', got: \" + use);\n  }\n}","typeGuard":"boolean isX509SvidKey(Map<String, ?> jwk) {\n  return \"x509-svid\".equals(jwk.get(\"use\"));\n}","tryCatchPattern":"try {\n  certs = SpiffeUtil.loadTrustBundleFromFile(bundlePath);\n} catch (IllegalArgumentException e) {\n  log.error(\"Trust bundle JWK has wrong 'use' value: \" + e.getMessage());\n  throw new TrustBundleLoadException(e);\n}","preventionTips":["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"],"tags":["grpc","spiffe","jwk","trust-bundle","validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}