{"record":{"id":"78d7c26e407cc870","repo":"grpc/grpc-java","slug":"validationresult-getvalidationdetails-server","errorCode":null,"errorMessage":"${validationResult.getValidationDetails()} (server-provided validation details)","messagePattern":"(.+?) \\(server-provided validation details\\)","errorType":"exception","errorClass":"CertificateException","httpStatus":null,"severity":"critical","filePath":"s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2ATrustManager.java","lineNumber":173,"sourceCode":"    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      throw new CertificateException(\"Failed to send request to S2A.\", e);\n    }\n    if (resp.hasStatus() && resp.getStatus().getCode() != 0) {\n      throw new CertificateException(\n          String.format(\n              \"Error occurred in response from S2A, error code: %d, error message: %s.\",\n              resp.getStatus().getCode(), resp.getStatus().getDetails()));\n    }\n\n    if (!resp.hasValidatePeerCertificateChainResp()) {\n      throw new CertificateException(\"No valid response received from S2A.\");\n    }\n\n    ValidatePeerCertificateChainResp validationResult = resp.getValidatePeerCertificateChainResp();\n    if (validationResult.getValidationResult()\n        != ValidatePeerCertificateChainResp.ValidationResult.SUCCESS) {\n      throw new CertificateException(validationResult.getValidationDetails());\n    }\n  }\n\n  private static ImmutableList<ByteString> certificateChainToDerChain(X509Certificate[] chain)\n      throws CertificateEncodingException {\n    ImmutableList.Builder<ByteString> derChain = ImmutableList.<ByteString>builder();\n    for (X509Certificate certificate : chain) {\n      derChain.add(ByteString.copyFrom(certificate.getEncoded()));\n    }\n    return derChain.build();\n  }\n}\n","sourceCodeStart":155,"sourceCodeEnd":186,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2ATrustManager.java#L155-L186","documentation":"When the S2A validates the peer certificate chain and returns a result other than SUCCESS, S2ATrustManager.checkPeerTrusted() throws a CertificateException whose message is the S2A-provided validation details. This is a genuine peer-certificate trust failure reported by the S2A during mTLS.","triggerScenarios":"checkClientTrusted/checkServerTrusted receives ValidatePeerCertificateChainResp whose ValidationResult != SUCCESS — the peer's certificate chain failed S2A-side validation, with getValidationDetails() explaining why.","commonSituations":"Peer presenting a cert from an untrusted CA or expired certificate; wrong trust domain configuration on the S2A; hostname/SAN mismatch in peer identity; rotated roots not yet propagated to the S2A.","solutions":["Read getValidationDetails() in the exception message to identify the exact validation failure ( expiry, untrusted root, SAN mismatch ).","Ensure the peer's certificate chain is valid and issued by a CA the S2A trusts.","Update the S2A's trust-domain/root configuration if certificates were recently rotated.","Verify both peers are configured with matching S2A trust domains."],"exampleFix":"// before\n// peer cert expired -> S2A rejects\n// after\n// renew peer certificate / propagate new roots to S2A trust config\ns2a.updateTrustBundle(newRoots);","handlingStrategy":"try-catch","validationCode":"// check peer cert basics before the handshake\nfor (X509Certificate cert : peerChain) {\n  cert.checkValidity(); // fails fast on expired/not-yet-valid certs\n}","typeGuard":null,"tryCatchPattern":"try {\n  trustManager.checkClientTrusted(chain, authType);\n} catch (CertificateException e) {\n  // message carries S2A validation details ( expired, untrusted root, SAN mismatch )\n  logger.warning(\"Peer cert rejected by S2A: \" + e.getMessage());\n  throw e; // do not bypass trust validation\n}","preventionTips":["Keep peer certificates renewed and chains complete.","Propagate root CA rotations to the S2A trust configuration promptly.","Ensure trust domains on both peers are configured consistently.","Never catch and ignore this exception — it signals a real trust failure."],"tags":["tls","certificate-validation","s2a","mtls","trust-chain"],"backgroundTag":"certificate-validation-failed","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"}