{"record":{"id":"02afe0bf331c77c9","repo":"grpc/grpc-java","slug":"error-occurred-in-response-from-s2a-error-code-02afe0","errorCode":null,"errorMessage":"Error occurred in response from S2A, error code: %d, error message: %s.","messagePattern":"Error occurred in response from S2A, error code: (.+?), error message: (.+?)\\.","errorType":"exception","errorClass":"CertificateException","httpStatus":null,"severity":"error","filePath":"s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2ATrustManager.java","lineNumber":160,"sourceCode":"    }\n\n    SessionReq.Builder reqBuilder =\n        SessionReq.newBuilder().setValidatePeerCertificateChainReq(validatePeerCertificateChainReq);\n    if (localIdentity.isPresent()) {\n      reqBuilder.setLocalIdentity(localIdentity.get().getIdentity());\n    }\n\n    SessionResp resp;\n    try {\n      resp = stub.send(reqBuilder.build());\n    } catch (IOException e) {\n      throw new CertificateException(\"Failed to send request to S2A.\", e);\n    } 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 {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2ATrustManager.java#L142-L178","documentation":"When the SessionResp from the S2A carries a non-zero status code, S2ATrustManager.checkPeerTrusted() throws a CertificateException formatted with the S2A-provided error code and message. This means the S2A itself reported an error processing the validation request, as opposed to a transport failure.","triggerScenarios":"checkClientTrusted/checkServerTrusted receives a SessionResp where resp.hasStatus() is true and resp.getStatus().getCode() != 0 — the S2A rejected or failed the request server-side.","commonSituations":"S2A not configured with the needed identity/key material; S2A internal error while validating the peer chain; version mismatch between client and S2A protobuf API.","solutions":["Read the S2A error code/message in the exception and map it to the S2A-side issue.","Verify the S2A is configured for the local identity and peer trust domains in use.","Check client/S2A proto version compatibility and upgrade accordingly."],"exampleFix":"// before\n// ignore S2A status, unclear why validation fails\n// after\ncatch (CertificateException e) {\n  logger.severe(\"S2A reported error: \" + e.getMessage()); // inspect code + details\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  trustManager.checkServerTrusted(chain, authType);\n} catch (CertificateException e) {\n  if (e.getMessage().startsWith(\"Error occurred in response from S2A\")) {\n    // parse embedded S2A error code/details for diagnosis\n    logger.severe(\"S2A-side error: \" + e.getMessage());\n  }\n  throw e;\n}","preventionTips":["Keep client library and S2A binary versions compatible.","Verify S2A configuration covers all local identities in use.","Log the formatted error code/details for S2A-side triage."],"tags":["tls","certificate-validation","s2a","grpc"],"backgroundTag":"api-error-response","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"}