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

  1. Ensure the served certificate chain includes the intermediate (issuer) certificate so ChainLink.Issuer is populated
  2. Fix the code building ChainLink so Leaf and Issuer are always set before fetching OCSP
  3. Provide a valid OCSPPeerConfig and Logger, or disable OCSP stapling if not configured
  4. 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

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


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