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

  1. Provide both tlsConfig.setCertChainFile() (the certificate chain PEM) and tlsConfig.setCertPrivateKey() (the private key PEM).
  2. If a passphrase protects the key, also set setCertPrivateKeyPassword().
  3. Verify both files are readable paths or classpath:/http URLs resolvable by the ResourceLoader.
  4. 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

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


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/459fd04f10410329. Report an issue: GitHub.