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.
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)
Solutions
- Ensure the full TLS options (tls block parsed into tlsOpts) are loaded before OCSP plugging; do not enable OCSP on a half-parsed config
- If embedding the server, populate all fields of the tlsConfigKind (config, tlsConfig, tlsOpts) before calling enableOCSP-related paths
- 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
- Load and parse the entire TLS config before enabling OCSP hooks; avoid partial hot reloads
- If embedding nats-server, always populate tlsConfigKind fully (config, tlsConfig, tlsOpts)
- Pin a stable server version and test config reloads with OCSP enabled in staging
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
- unable to plug TLS verify connection, config is nil
- OCSP peer verification for client connections requires TLS v
- no hostport specified
- websocket requires TLS configuration
- error opening config file: %v
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/7bdcf5b5637a8811.
Report an issue: GitHub.