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

  1. Set `root_cert` in connection.json to the PEM-encoded CA/root certificate that signs the chaincode's server cert
  2. Ensure the release script copies the root cert into the release directory
  3. 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

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

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/86fc6f468549a2e4. Report an issue: GitHub.