hyperledger/fabric · error
chaincode tls root cert not provided
Error message
chaincode tls root cert not provided
What it means
Even without client auth, a TLS connection to the chaincode server needs the chaincode's root CA certificate to verify the server; connection.json without `root_cert` leaves the peer unable to trust the chaincode endpoint.
Source
Thrown at core/container/externalbuilder/instance.go:101
connInfo.ClientConfig.DialTimeout = time.Duration(c.DialTimeout)
if connInfo.ClientConfig.DialTimeout == 0 {
connInfo.ClientConfig.DialTimeout = DialTimeout
}
// we can expose this if necessary
connInfo.ClientConfig.KaOpts = comm.DefaultKeepaliveOptions
if !c.TLSRequired {
return connInfo, nil
}
if c.ClientAuthRequired && c.ClientKey == "" {
return nil, errors.New("chaincode tls key not provided")
}
if c.ClientAuthRequired && c.ClientCert == "" {
return nil, errors.New("chaincode tls cert not provided")
}
if c.RootCert == "" {
return nil, errors.New("chaincode tls root cert not provided")
}
connInfo.ClientConfig.SecOpts.UseTLS = true
if c.ClientAuthRequired {
connInfo.ClientConfig.SecOpts.RequireClientCert = true
connInfo.ClientConfig.SecOpts.Certificate = []byte(c.ClientCert)
connInfo.ClientConfig.SecOpts.Key = []byte(c.ClientKey)
connInfo.ClientConfig.SecOpts.ServerNameOverride = c.Domain
}
connInfo.ClientConfig.SecOpts.ServerRootCAs = [][]byte{[]byte(c.RootCert)}
return connInfo, nil
}
func (i *Instance) ChaincodeServerReleaseDir() string {
return filepath.Join(i.ReleaseDir, CCServerReleaseDir)View on GitHub (pinned to 2736b63f8f)
Solutions
- Set `root_cert` in connection.json to the PEM-encoded CA/root certificate that signs the chaincode's server cert
- Ensure the release script copies the root cert into the release directory
- If TLS is not intended, set tls_required false in connection.json
Example fix
// before
{"tls_required":true,"address":"cc:7052"}
// after
{"tls_required":true,"address":"cc:7052","root_cert":"root.pem"} Defensive patterns
Strategy: validation
Validate before calling
var ud ChaincodeServerUserData
json.Unmarshal(connJSON, &ud)
if ud.TLSRequired && ud.RootCert == "" {
return errors.New("root_cert PEM required when tls_required is true")
}
if block, _ := pem.Decode([]byte(ud.RootCert)); block == nil {
return errors.New("root_cert is not PEM encoded")
} Try / catch
info, err := ud.ChaincodeServerInfo(cryptoDir)
if err != nil && strings.Contains(err.Error(), "root cert not provided") {
return fmt.Errorf("provide root_cert (CA of the chaincode server cert) or set tls_required=false: %w", err)
} Prevention
- Copy the chaincode CA cert into the release dir whenever TLS is enabled
- Use a stable crypto dir layout so root_cert paths are predictable
- Toggle tls_required consistently between chaincode config and connection.json
When it happens
Trigger: connection.json sets tls_required true (client auth not required) but `root_cert` is empty when ChaincodeServerInfo sets SecOpts.UseTLS.
Common situations: TLS enabled on the chaincode but the CA cert not copied into the release dir; self-signed cert generated but never published; field misnamed in connection.json.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- chaincode tls key not provided
- chaincode tls cert not provided
- chaincode address not provided
- without a system channel, a follower should have been create
- node identity certificate %s is not a valid PEM
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/86fc6f468549a2e4.
Report an issue: GitHub.