nats-io/nats-server · error

OCSP peer verification for client connections requires TLS v

Error message

OCSP peer verification for client connections requires TLS verify (mTLS) to be enabled

What it means

Raised in Server.plugTLSOCSPPeer (server/ocsp_peer.go:152) when OCSP peer verification is requested for client (or non-spoke leaf) connections but the TLS config does not set verify (mutual TLS). The VerifyConnection hook inspects peer verified chains, which only exist when the server requests and verifies client certificates; certidp.ErrMTLSRequired is returned so startup fails instead of silently verifying nothing.

Source

Thrown at server/ocsp_peer.go:152

	return chains[0][0]
}

// plugTLSOCSPPeer will plug the TLS handshake lifecycle for client mTLS connections and Leaf connections
func (s *Server) plugTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) {
	if config == nil || config.tlsConfig == nil {
		return nil, false, errors.New(certidp.ErrUnableToPlugTLSEmptyConfig)
	}
	kind := config.kind
	isSpoke := config.isLeafSpoke
	tcOpts := config.tlsOpts
	if tcOpts == nil || tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify {
		return nil, false, nil
	}
	s.Debugf(certidp.DbgPlugTLSForKind, config.kind)
	// peer is a tls client
	if kind == kindStringMap[CLIENT] || (kind == kindStringMap[LEAF] && !isSpoke) {
		if !tcOpts.Verify {
			return nil, false, errors.New(certidp.ErrMTLSRequired)
		}
		return s.plugClientTLSOCSPPeer(config)
	}
	// peer is a tls server
	if kind == kindStringMap[LEAF] && isSpoke {
		return s.plugServerTLSOCSPPeer(config)
	}
	return nil, false, nil
}

func (s *Server) plugClientTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) {
	if config == nil || config.tlsConfig == nil || config.tlsOpts == nil {
		return nil, false, errors.New(certidp.ErrUnableToPlugTLSClient)
	}
	tc := config.tlsConfig
	tcOpts := config.tlsOpts
	kind := config.kind
	if tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Enable mTLS in the same TLS block: set verify: true and provide ca_file so client certificates are required and verified
  2. For leaf connections, ensure the topology matches: OCSP peer verification of servers applies to the spoke side; use client-side (hub) config where appropriate
  3. Re-test the handshake with a client certificate to confirm mTLS is enforced before OCSP hooks engage

Example fix

# before
tls {
  cert_file: "./server-cert.pem"
  key_file: "./server-key.pem"
}
ocsp_peer { verify: true }
# after: mTLS required for OCSP peer verification
tls {
  cert_file: "./server-cert.pem"
  key_file: "./server-key.pem"
  ca_file: "./ca.pem"
  verify: true
}
ocsp_peer { verify: true }
Defensive patterns

Strategy: validation

Validate before calling

# preflight check: OCSP peer verify requires mTLS (verify: true + ca_file) in the same tls block
if ocsp_peer.get('verify') and not (tls.get('verify') and tls.get('ca_file')):
    raise SystemExit('ocsp_peer.verify requires tls verify (mTLS) with ca_file')

Try / catch

// Go: wrap server start and explain the mTLS requirement
if err := srv.Start(); err != nil && strings.Contains(err.Error(), "OCSP peer verification") && strings.Contains(err.Error(), "mTLS") {
    log.Fatalf("Enable mTLS (verify: true + ca_file) before OCSP peer verification: %v", err)
}

Prevention

When it happens

Trigger: Config defines ocsp_peer { verify: true } under a TLS block for CLIENT connections (or LEAF connections where the server is not the spoke) while tls verify (i.e. ca_file-based mTLS client cert verification) is absent or false.

Common situations: Enabling OCSP peer checks but forgetting ca_file / verify: true in the tls block; leaf-node setups where the spoke/s Hub roles are confused so the server-side path is chosen; documenting mTLS elsewhere but leaving the leaf's TLS block client-auth-free.

Understand the failure class

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/37488b604b6bfe7b. Report an issue: GitHub.