hyperledger/fabric · error

must set either [peer.tls.key.file and peer.tls.cert.file] o

Error message

must set either [peer.tls.key.file and peer.tls.cert.file] or [peer.tls.clientKey.file and peer.tls.clientCert.file]when peer.tls.clientAuthEnabled is set to true

What it means

GetClientCertificate requires a TLS keypair when peer.tls.clientAuthEnabled is true. If neither the client pair (clientKey.file/clientCert.file) nor the server pair (key.file/cert.file) is configured at all, this error is returned telling the operator which combinations are acceptable.

Source

Thrown at core/peer/config.go:489

		}
		keyPath = config.GetPath("peer.tls.clientKey.file")
		certPath = config.GetPath("peer.tls.clientCert.file")

	} else {
		// use the TLS server keypair
		keyPath = viper.GetString("peer.tls.key.file")
		certPath = viper.GetString("peer.tls.cert.file")

		if keyPath != "" || certPath != "" {
			// need both keyPath and certPath to be set
			if keyPath == "" || certPath == "" {
				return cert, errors.New("peer.tls.key.file and " +
					"peer.tls.cert.file must both be set or must both be empty")
			}
			keyPath = config.GetPath("peer.tls.key.file")
			certPath = config.GetPath("peer.tls.cert.file")
		} else {
			return cert, errors.New("must set either " +
				"[peer.tls.key.file and peer.tls.cert.file] or " +
				"[peer.tls.clientKey.file and peer.tls.clientCert.file]" +
				"when peer.tls.clientAuthEnabled is set to true")
		}
	}
	// get the keypair from the file system
	clientKey, err := os.ReadFile(keyPath)
	if err != nil {
		return cert, errors.WithMessage(err,
			"error loading client TLS key")
	}
	clientCert, err := os.ReadFile(certPath)
	if err != nil {
		return cert, errors.WithMessage(err,
			"error loading client TLS certificate")
	}
	cert, err = tls.X509KeyPair(clientCert, clientKey)
	if err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set peer.tls.clientKey.file and peer.tls.clientCert.file (preferred explicit client pair).
  2. Alternatively ensure peer.tls.key.file and peer.tls.cert.file are both set.
  3. Or disable clientAuthEnabled if mutual TLS is not required.
  4. Verify env vars actually reach the process (CORE_PEER_TLS_* prefix correct, no env stripping).

Example fix

// before
tls:
  clientAuthEnabled: true
  # no key/cert files configured
// after
tls:
  clientAuthEnabled: true
  clientKey.file: /etc/hyperledger/fabric/tls/client.key
  clientCert.file: /etc/hyperledger/fabric/tls/client.crt
Defensive patterns

Strategy: validation

Validate before calling

if viper.GetBool("peer.tls.clientAuthEnabled") {
  hasClientPair := viper.GetString("peer.tls.clientKey.file") != "" && viper.GetString("peer.tls.clientCert.file") != ""
  hasServerPair := viper.GetString("peer.tls.key.file") != "" && viper.GetString("peer.tls.cert.file") != ""
  if !hasClientPair && !hasServerPair {
    return errors.New("clientAuthEnabled requires a complete key/cert pair")
  }
}

Try / catch

cert, err := GetClientCertificate()
if err != nil && strings.Contains(err.Error(), "clientAuthEnabled is set to true") {
  log.Fatalf("provide a TLS key/cert pair when client auth is enabled: %v", err)
}

Prevention

When it happens

Trigger: peer.tls.clientAuthEnabled=true while all four of peer.tls.clientKey.file, peer.tls.clientCert.file, peer.tls.key.file, peer.tls.cert.file are empty.

Common situations: Enabling CORE_PEER_TLS_CLIENTAUTH_ENABLED without providing any key files; inheriting a config from a TLS-disabled peer and flipping clientAuthEnabled on; misconfigured env prefix so viper sees nothing.

Understand the failure class

Related errors


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