alibaba/nacos · error · IllegalArgumentException
client certChainFile or certPrivateKey must be not null
Error message
client certChainFile or certPrivateKey must be not null
What it means
GrpcClient.buildSslContext() requires both certChainFile and certPrivateKey when mutual TLS authentication is enabled. If either is blank it throws IllegalArgumentException before loading the key material, because mTLS cannot present a client identity without both halves.
Source
Thrown at common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java:582
}
if (StringUtils.isNotBlank(tlsConfig.getCiphers())) {
builder.ciphers(Arrays.asList(tlsConfig.getCiphers().split(",")));
}
if (tlsConfig.getTrustAll()) {
builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
} else {
if (StringUtils.isBlank(tlsConfig.getTrustCollectionCertFile())) {
throw new IllegalArgumentException("trustCollectionCertFile must be not null");
}
Resource resource =
resourceLoader.getResource(tlsConfig.getTrustCollectionCertFile());
builder.trustManager(resource.getInputStream());
}
if (tlsConfig.getMutualAuthEnable()) {
if (StringUtils.isBlank(tlsConfig.getCertChainFile()) || StringUtils.isBlank(
tlsConfig.getCertPrivateKey())) {
throw new IllegalArgumentException(
"client certChainFile or certPrivateKey must be not null");
}
Resource certChainFile = resourceLoader.getResource(tlsConfig.getCertChainFile());
Resource privateKey = resourceLoader.getResource(tlsConfig.getCertPrivateKey());
builder.keyManager(certChainFile.getInputStream(), privateKey.getInputStream(),
tlsConfig.getCertPrivateKeyPassword());
}
return Optional.of(builder.build());
} catch (Exception e) {
throw new RuntimeException("Unable to build SslContext", e);
}
}
private ManagedChannelBuilder buildChannel(String serverIp, int port,
Optional<SslContext> sslContext) {
if (sslContext.isPresent()) {
return NettyChannelBuilder.forAddress(serverIp, port)
.negotiationType(NegotiationType.TLS)View on GitHub (pinned to 9b989acdf1)
Solutions
- Provide both tlsConfig.setCertChainFile() (the certificate chain PEM) and tlsConfig.setCertPrivateKey() (the private key PEM).
- If a passphrase protects the key, also set setCertPrivateKeyPassword().
- Verify both files are readable paths or classpath:/http URLs resolvable by the ResourceLoader.
- If mTLS is not actually required, set mutualAuthEnable=false.
Example fix
// before — mTLS on, only key supplied
RpcClientTlsConfig tls = new RpcClientTlsConfig();
tls.setEnableTls(true);
tls.setMutualAuthEnable(true);
tls.setCertPrivateKey("/etc/nacos/certs/client.key");
// after — both halves supplied
tls.setCertChainFile("/etc/nacos/certs/client.crt");
tls.setCertPrivateKey("/etc/nacos/certs/client.key"); Defensive patterns
Strategy: validation
Validate before calling
static void validateMtls(RpcClientTlsConfig tls) {
if (Boolean.TRUE.equals(tls.getMutualAuthEnable())) {
if (isBlank(tls.getCertChainFile()) || isBlank(tls.getCertPrivateKey())) {
throw new IllegalArgumentException(
"mTLS enabled: must set both certChainFile and certPrivateKey");
}
}
} Try / catch
try {
client.start();
} catch (RuntimeException re) {
if (re.getMessage().contains("certChainFile")) {
// supply the missing cert chain / key, then retry
} else { throw re; }
} Prevention
- Validate mTLS config before start(): both certChainFile and certPrivateKey must be set.
- Include cert password handling if the key is encrypted.
- Add a config validator to catch blank fields at deploy/test time.
When it happens
Trigger: Constructing an RpcClientTlsConfig with mutualAuthEnable=true but leaving certChainFile or certPrivateKey unset/blank. The check runs during buildSslContext() at client start.
Common situations: Enabling mTLS from config but only providing the private key (or only the chain); property-key typos; environment-specific paths not set in the deployed environment; copying a config block that omitted the cert fields.
Related errors
- trustCollectionCertFile must be not null
- Unable to build SslContext
- {e.getErrCode()}
- PARAMETER_MISSING
- MCP_SERVER_NOT_FOUND
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/459fd04f10410329.
Report an issue: GitHub.