hyperledger/fabric · critical
panic(err)
Error message
panic(err)
What it means
CommonClient.Certificate retrieves the client TLS certificate from the security options; if SecOpts.ClientCertificate() returns an error (e.g. the configured cert/key files cannot be loaded or parsed), the code panics rather than returning an error. This is an intentional unrecoverable failure: the client was configured to require a client cert but none can be obtained.
Source
Thrown at internal/peer/common/common.go:105
type CommonClient struct {
clientConfig comm.ClientConfig
address string
}
func newCommonClient(address string, clientConfig comm.ClientConfig) (*CommonClient, error) {
return &CommonClient{
clientConfig: clientConfig,
address: address,
}, nil
}
func (cc *CommonClient) Certificate() tls.Certificate {
if !cc.clientConfig.SecOpts.RequireClientCert {
return tls.Certificate{}
}
cert, err := cc.clientConfig.SecOpts.ClientCertificate()
if err != nil {
panic(err)
}
return cert
}
// Dial will create a new gRPC client connection to the provided
// address. The options used for the dial are sourced from the
// ClientConfig provided to the constructor.
func (cc *CommonClient) Dial(address string) (*grpc.ClientConn, error) {
return cc.clientConfig.Dial(address)
}
func init() {
GetEndorserClientFnc = GetEndorserClient
GetDefaultSignerFnc = GetDefaultSigner
GetBroadcastClientFnc = GetBroadcastClient
GetOrdererEndpointOfChainFnc = GetOrdererEndpointOfChain
GetDeliverClientFnc = GetDeliverClient
GetPeerDeliverClientFnc = GetPeerDeliverClientView on GitHub (pinned to 2736b63f8f)
Solutions
- Check that the client certificate and key file paths in config (SecOpts) exist and are readable
- Verify the key matches the certificate (re-export the pair from your MSP if unsure)
- Ensure RequireClientCert is only true when valid client credentials are actually configured
- Wrap client construction early so the panic happens at startup, not mid-operation
Example fix
// before
// SecOpts{RequireClientCert: true, Key: nil} -> panic(err)
// after
secOpts := &fab.CommonClientConfig.SecOpts
secOpts.RequireClientCert = true
secOpts.ClientCertFile = "/path/to/client.crt"
secOpts.ClientKeyFile = "/path/to/client.key" // valid, matching pair Defensive patterns
Strategy: validation
Validate before calling
// validate cert material before constructing the client
certFile, keyFile := cfg.ClientCertFile, cfg.ClientKeyFile
if certFile == "" || keyFile == "" { return errors.New("client cert/key required when RequireClientCert=true") }
if _, err := tls.LoadX509KeyPair(certFile, keyFile); err != nil {
return fmt.Errorf("invalid client cert/key: %w", err)
} Type guard
func hasValidClientCert(opts *SecOpts) bool {
if !opts.RequireClientCert { return true }
cert, err := opts.ClientCertificate()
return err == nil && len(cert.Certificate) > 0
} Try / catch
func safeCertificate(cc *common.CommonClient) (cert tls.Certificate, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("client certificate unavailable: %v", r)
}
}()
return cc.Certificate(), nil
} Prevention
- Verify cert/key file paths exist and are readable before starting the client
- Check that key and certificate form a matching pair (compare public keys)
- Recover() around panicking client setup in long-running services
- Keep RequireClientCert=false unless valid client credentials are guaranteed
When it happens
Trigger: Constructing a CommonClient with SecOpts.RequireClientCert=true but the ClientCertificate() call fails because tls client cert/key file paths are wrong, files unreadable, or key/cert mismatch.
Common situations: CORE_VM/CLI config pointing to nonexistent cert paths; expired or malformed PEM files; key and cert pair mismatched; running in a container without the mounted certificate volume.
Related errors
- failed to access client TLS configuration: %w
- Error in instantiating ledger provider: %+v
- Empty policy element
- cannot load client cert for consenter %s:%d: %s
- cannot load server cert for consenter %s:%d: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/b8dc04cdce0f3777.
Report an issue: GitHub.