{"record":{"id":"c944fd16e984984e","repo":"grpc/grpc-java","slug":"certificate-can-t-be-parsed-certificate-loading-f","errorCode":null,"errorMessage":"Certificate can't be parsed. Certificate loading for trust domain '%s' failed.","messagePattern":"Certificate can't be parsed\\. 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":247,"sourceCode":"      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 {\n        Collection<? extends Certificate> certs = CertificateFactory.getInstance(\"X509\")\n            .generateCertificates(stream);\n        X509Certificate[] certsArray = certs.toArray(new X509Certificate[0]);\n        assert certsArray.length == 1;\n        result.add(certsArray[0]);\n      } catch (CertificateException e) {\n        throw new IllegalArgumentException(String.format(\"Certificate can't be parsed. Certificate \"\n            + \"loading for trust domain '%s' failed.\", trustDomainName), e);\n      }\n    }\n    return result;\n  }\n\n  /**\n   * Represents a SPIFFE ID as defined in the SPIFFE standard.\n   * @see <a href=\"https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md\">Standard</a>\n   */\n  public static class SpiffeId {\n\n    private final String trustDomain;\n    private final String path;\n\n    private SpiffeId(String trustDomain, String path) {\n      this.trustDomain = trustDomain;\n      this.path = path;","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/SpiffeUtil.java#L229-L265","documentation":"SpiffeUtil.extractCert decodes the base64 x5c certificate of each JWK and parses it as X.509 via CertificateFactory. If parsing throws CertificateException (corrupt DER, wrong encoding, non-certificate bytes), it is wrapped in this IllegalArgumentException with the trust domain name.","triggerScenarios":"A trust bundle JWK's x5c entry contains bytes that are not a valid X.509 certificate — truncated base64, a PEM header pasted into x5c, or an unrelated key blob — during loadTrustBundleFromFile.","commonSituations":"Manually assembled bundles where a PEM string (-----BEGIN CERTIFICATE-----) was placed in x5c instead of the base64 DER body; damaged files transferred via copy/paste or mis-encoded downloads.","solutions":["Ensure x5c contains base64 DER only: strip PEM headers/footers and keep the raw base64 body","Verify the cert independently: openssl x509 -inform DER -in cert.der -text","Regenerate the bundle from SPIRE rather than hand-copying certificates","Confirm the file was not truncated or line-wrapped by editors/transfer tools"],"exampleFix":"// before\n\"x5c\": [\"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\"]\n// after\n\"x5c\": [\"MIIBdzCCAV2gAwIBAgIUP...base64-DER-only...\"]","handlingStrategy":"try-catch","validationCode":"// Decode and sanity-check x5c before loading\nbyte[] der = java.util.Base64.getMimeDecoder().decode((String) jwk.get(\"x5c\").get(0));\ntry {\n  new javax.crypto.spec.X509EncodedKeySpec(der); // basic length sanity\n  java.security.cert.CertificateFactory.getInstance(\"X509\")\n      .generateCertificate(new java.io.ByteArrayInputStream(der));\n} catch (Exception e) {\n  throw new IllegalStateException(\"x5c entry is not a parseable X.509 cert\", e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  certs = SpiffeUtil.loadTrustBundleFromFile(bundlePath);\n} catch (IllegalArgumentException e) {\n  log.error(\"Unparseable certificate in trust bundle: \" + e.getMessage(), e.getCause());\n  throw new TrustBundleLoadException(e);\n}","preventionTips":["Put base64 DER only in x5c — strip PEM headers/footers and newlines","openssl-verify each cert before bundling","Avoid manual copy/paste of certificates; script bundle generation"],"tags":["grpc","spiffe","x509","certificate","trust-bundle"],"backgroundTag":"invalid-certificate-format","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"}