{"record":{"id":"c15c6b262fd43e60","repo":"apache/skywalking","slug":"admin-server-failed-to-build-admin-grpc-client-ss","errorCode":null,"errorMessage":"admin-server: failed to build admin gRPC client SSL context","messagePattern":"admin-server: failed to build admin gRPC client SSL context","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"oap-server/server-admin/admin-server/src/main/java/org/apache/skywalking/oap/server/admin/server/module/AdminServerModuleProvider.java","lineNumber":187,"sourceCode":"        // in plaintext at a port the server is only willing to handshake. Fail fast at\n        // boot rather than letting the cluster silently break at first reconcile.\n        SslContext clientSslContext = null;\n        if (moduleConfig.isGRPCSslEnabled()) {\n            if (moduleConfig.getGRPCSslTrustedCAsPath() == null\n                || moduleConfig.getGRPCSslTrustedCAsPath().isEmpty()) {\n                throw new IllegalStateException(\n                    \"admin-server: gRPCSslEnabled=true but gRPCSslTrustedCAsPath is empty. \"\n                        + \"The admin-internal gRPC bus needs a CA bundle on every node so \"\n                        + \"peer channels can establish TLS to the server's cert. Set \"\n                        + \"SW_ADMIN_SERVER_GRPC_SSL_TRUSTED_CAS_PATH (or \"\n                        + \"admin-server.gRPCSslTrustedCAsPath in application.yml) on every \"\n                        + \"OAP, or set gRPCSslEnabled=false everywhere.\");\n            }\n            try {\n                clientSslContext = AdminClusterChannelManagerImpl.clientSslContext(\n                    moduleConfig.getGRPCSslTrustedCAsPath());\n            } catch (final Exception e) {\n                throw new IllegalStateException(\n                    \"admin-server: failed to build admin gRPC client SSL context\", e);\n            }\n        }\n        peerChannelManager = new AdminClusterChannelManagerImpl(\n            () -> getManager().find(ClusterModule.NAME).provider()\n                              .getService(ClusterNodesQuery.class),\n            moduleConfig.getGRPCPort(),\n            moduleConfig.getInternalCommunicationTimeout(),\n            clientSslContext);\n        registerServiceImplementation(AdminClusterChannelManager.class, peerChannelManager);\n    }\n\n    @Override\n    public void start() {\n        // Routes are added by feature modules in their start() phase via the\n        // HTTPHandlerRegister service exposed above. Channel manager is\n        // already registered in prepare() with a lazy ClusterNodesQuery\n        // supplier; nothing else to do here.","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-admin/admin-server/src/main/java/org/apache/skywalking/oap/server/admin/server/module/AdminServerModuleProvider.java#L169-L205","documentation":"After the empty-path check passes, the provider builds a Netty client SslContext from the configured CA bundle via AdminClusterChannelManagerImpl.clientSslContext(). Any failure there (file not found, unreadable, malformed PEM, unsupported PKCS format) is wrapped in this IllegalStateException with the original exception as cause, aborting module start.","triggerScenarios":"gRPCSslTrustedCAsPath points to a path that does not exist in the container, is not readable by the OAP process, is an empty or corrupted PEM, or contains a certificate format the TLS stack rejects. The cause chain carries the underlying exception.","commonSituations":"Docker/K8s deployments where the TLS secret was not mounted at the configured path or mounted with wrong permissions; rotating certs and truncating the file; PEM with only a private key instead of CA certificates; wrong architecture binary issues after image changes.","solutions":["Read the chained cause in the stack trace (FileNotFoundException, PEMException, etc.) — it names the real problem","Verify the path exists inside the container (kubectl exec / docker run -- ls) and is readable by the OAP user","Validate the file is a PEM CA bundle (openssl x509 -in ca.pem -noout -text) and re-issue if malformed","Ensure mounts (secret volumes, configmaps) actually project the file at that path"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Pre-flight: verify the CA bundle parses before OAP start\nopenssl x509 -in \"$SW_ADMIN_SERVER_GRPC_SSL_TRUSTED_CAS_PATH\" -noout || { echo 'bad CA bundle'; exit 1; }","typeGuard":null,"tryCatchPattern":"This throws IllegalStateException at module start with the underlying SSL exception as cause — inspect e.getCause() (PEMException, FileNotFoundException) to pinpoint the file problem; do not catch-and-continue in production, fix the mount/file.","preventionTips":["Smoke-test TLS material in the container image build (openssl verify) rather than at OAP boot","Mount secrets read-only and verify projected paths with an initContainer or readiness probe"],"tags":["admin-server","tls","certificates","deployment","startup"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}