nats-io/nats-server · error

unable to register client OCSP verification

Error message

unable to register client OCSP verification

What it means

Raised in Server.plugClientTLSOCSPPeer (server/ocsp_peer.go:165) when the client-kind TLS wrapper passed from plugTLSOCSPPeer is missing its config, tlsConfig, or tlsOpts, so the OCSP VerifyConnection callback cannot be registered on the client TLS config (certidp.ErrUnableToPlugTLSClient). It is a defensive invariant check that fails server startup rather than allowing OCSP peer verification to be silently skipped.

Solutions

  1. Ensure the full TLS options (tls block parsed into tlsOpts) are loaded before OCSP plugging; do not enable OCSP on a half-parsed config
  2. If embedding the server, populate all fields of the tlsConfigKind (config, tlsConfig, tlsOpts) before calling enableOCSP-related paths
  3. Retry or re-trigger the reload with the complete config; if it persists, capture the config file and report with the NATS server version
Defensive patterns

Strategy: try-catch

Try / catch

// Go: catch the startup failure and retry with a fully loaded config
if err := srv.Start(); err != nil && strings.Contains(err.Error(), "unable to register client OCSP verification") {
    log.Errorf("OCSP client plugging failed: %v; reloading full TLS config", err)
    reloadFullTLSConfig()
    srv.Start()
}

Prevention

When it happens

Trigger: plugClientTLSOCSPPeer receives a *tlsConfigKind whose tlsOpts was nil even though an earlier coarse check passed, or whose tlsConfig is nil — an internal inconsistency when enableOCSP/reloadOCSP assembles the client TLS config while OCSP peer verify is enabled.

Common situations: Partial config loads during hot reload where TLS options are parsed after the OCSP plugging step; custom embedding of the server that constructs tlsConfigKind manually and leaves tlsOpts unset; race during concurrent reload/OCSP enable.

Related errors


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

Appendix: source

Thrown at server/ocsp_peer.go:165

	}
	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 {
		return tc, false, nil
	}
	tc.VerifyConnection = func(cs tls.ConnectionState) error {
		if !s.tlsClientOCSPValid(cs.VerifiedChains, tcOpts.OCSPPeerConfig) {
			s.sendOCSPPeerRejectEvent(kind, peerFromVerifiedChains(cs.VerifiedChains), certidp.MsgTLSClientRejectConnection)
			return errors.New(certidp.MsgTLSClientRejectConnection)
		}
		return nil
	}
	return tc, true, nil
}

func (s *Server) plugServerTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) {

View on GitHub (pinned to 3a66a489d2)