nats-io/nats-server · error
invalid chain link
Error message
invalid chain link
What it means
FetchOCSPResponse returns this error (ErrInvalidChainlink) when given a chain link it cannot use for an OCSP fetch: a nil link, a link missing the Leaf or Issuer certificate, or nil opts/log parameters. Without both certificates in the link, an OCSP request (which must name the issuer) cannot be constructed.
Source
Thrown at server/certidp/ocsp_responder.go:31
package certidp
import (
"encoding/base64"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
"golang.org/x/crypto/ocsp"
)
func FetchOCSPResponse(link *ChainLink, opts *OCSPPeerConfig, log *Log) ([]byte, error) {
if link == nil || link.Leaf == nil || link.Issuer == nil || opts == nil || log == nil {
return nil, errors.New(ErrInvalidChainlink)
}
timeout := time.Duration(opts.Timeout * float64(time.Second))
if timeout <= 0*time.Second {
timeout = DefaultOCSPResponderTimeout
}
getRequestBytes := func(u string, hc *http.Client) ([]byte, error) {
resp, err := hc.Get(u)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf(ErrBadResponderHTTPStatus, resp.StatusCode)
}
return io.ReadAll(resp.Body)
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Ensure the served certificate chain includes the intermediate (issuer) certificate so ChainLink.Issuer is populated
- Fix the code building ChainLink so Leaf and Issuer are always set before fetching OCSP
- Provide a valid OCSPPeerConfig and Logger, or disable OCSP stapling if not configured
- Validate the peer's chain completeness before enabling CertIDP/OCSP checks
Example fix
// before
link := &ChainLink{Leaf: cert} // Issuer missing
resp, _ := certidp.FetchOCSPResponse(link, opts, log)
// after
if cert.Chain != nil && len(cert.Chain) > 1 {
link := &ChainLink{Leaf: cert, Issuer: cert.Chain[1]}
resp, err := certidp.FetchOCSPResponse(link, opts, log)
} Defensive patterns
Strategy: validation
Validate before calling
func canFetchOCSP(link *certidp.ChainLink, opts *certidp.OCSPPeerConfig) bool {
return link != nil && link.Leaf != nil && link.Issuer != nil && opts != nil
}
if !canFetchOCSP(link, opts) {
return fmt.Errorf("incomplete chain link: leaf/issuer required for OCSP")
} Type guard
func validChainLink(l *certidp.ChainLink) bool {
return l != nil && l.Leaf != nil && l.Issuer != nil
} Try / catch
resp, err := certidp.FetchOCSPResponse(link, opts, log)
if err != nil {
log.Warnf("OCSP fetch failed for %s: %v", link.Leaf.Subject, err)
return false, err
} Prevention
- Always serve/inspect the full chain including intermediates
- Check Leaf and Issuer are non-nil before OCSP calls
- Configure OCSPPeerConfig completely before enabling CertIDP
When it happens
Trigger: Calling FetchOCSPChain/certOCSPGood path with a ChainLink whose Leaf or Issuer fields are nil, or passing nil for link, opts, or log.
Common situations: Incomplete certificate chains presented by peers (missing intermediate), chain assembly bugs in TLS config, or OCSP checking enabled without proper responder configuration.
Related errors
- no available OCSP servers
- expected 'cert_store' to be a valid non-empty string
- expected 'cert_match_by' to be a valid non-empty string
- expected 'cert_match' to be a valid non-empty string
- unable to plug TLS verify connection, config is nil
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/8148d045cae84221.
Report an issue: GitHub.