hyperledger/fabric · critical

unable to load cert at '%s'

Error message

unable to load cert at '%s'

What it means

Same flow as the key load: after successfully reading the key, loadDeliverServiceConfig reads the TLS certificate file and panics with this wrapped error if os.ReadFile fails. It aborts peer startup because the delivery service cannot be configured without its certificate.

Source

Thrown at core/deliverservice/config.go:206

	if c.SecOpts.RequireClientCert {
		certFile := config.GetPath("peer.tls.clientCert.file")
		if certFile == "" {
			certFile = config.GetPath("peer.tls.cert.file")
		}

		keyFile := config.GetPath("peer.tls.clientKey.file")
		if keyFile == "" {
			keyFile = config.GetPath("peer.tls.key.file")
		}

		keyPEM, err := os.ReadFile(keyFile)
		if err != nil {
			panic(errors.WithMessagef(err, "unable to load key at '%s'", keyFile))
		}
		c.SecOpts.Key = keyPEM
		certPEM, err := os.ReadFile(certFile)
		if err != nil {
			panic(errors.WithMessagef(err, "unable to load cert at '%s'", certFile))
		}
		c.SecOpts.Certificate = certPEM
	}

	overridesMap, err := LoadOverridesMap()
	if err != nil {
		panic(err)
	}

	c.OrdererEndpointOverrides = overridesMap

	policyKey := "peer.deliveryclient.policy"
	policyMissing := !viper.IsSet(policyKey)
	policy := DefaultPolicy
	if policyMissing {
		logger.Infof("%s is not set, defaulting to %s.", policyKey, policy)
	} else {
		policy = viper.GetString(policyKey)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the cert file path configured for the deliver service / peer.tls.cert.file exists and is readable.
  2. Confirm the TLS certificate volume/secret is mounted correctly in your container orchestration.
  3. Ensure the cert matches the configured key (same pair) and is PEM-encoded.
  4. Use absolute, verified paths and a startup preflight that checks both key and cert before launching the peer.

Example fix

// before
CORE_PEER_TLS_CERT_FILE=/tls/server.crt   // not mounted in container
// after
# in deployment yaml
volumeMounts:
  - name: tls
    mountPath: /tls
# with CORE_PEER_TLS_CERT_FILE=/tls/server.crt verified present
Defensive patterns

Strategy: validation

Validate before calling

certPath := viper.GetString("peer.tls.cert.file")
if certPath == "" {
    return errors.New("peer.tls.cert.file not configured")
}
if fi, err := os.Stat(certPath); err != nil || fi.IsDir() {
    return fmt.Errorf("TLS cert file missing: %s", certPath)
}
blk, _ := pem.Decode(mustRead(certPath))
if blk == nil || blk.Type != "CERTIFICATE" {
    return errors.New("file is not a PEM certificate")
}

Try / catch

// Config loading panics; preflight before starting the peer and, on failure,
// surface errors.Cause(err) to distinguish missing file vs permission denial.

Prevention

When it happens

Trigger: TLS enabled but the certificate file path (deliver service cert config or peer.tls.cert.file) is empty, nonexistent, or unreadable when GlobalConfig initializes.

Common situations: Cert file not mounted into the container; typo in the cert path in core.yaml; expired/rotated certs removed before peer restart; permissions tightened by secret-management tooling.

Related errors


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