nats-io/nats-server · error

%s invalid ca basic constraints: is not ca

Error message

%s invalid ca basic constraints: is not ca

What it means

After resolving the issuer, getOCSPIssuer enforces that the issuer certificate actually has IsCA set (BasicConstraints CA=true). A non-CA certificate selected as issuer is rejected with the issuer's subject in the message.

Source

Thrown at server/ocsp.go:968

		}
	}

	// Specify bundled intermediate CA store
	for _, certBytes := range chain {
		cert, err := x509.ParseCertificate(certBytes)
		if err != nil {
			return nil, fmt.Errorf("failed to parse cert: %v", err)
		}
		certBundle = append(certBundle, cert)
	}

	issuer, err = getOCSPIssuerLocally(trustedCAs, certBundle)
	if err != nil || issuer == nil {
		return nil, fmt.Errorf("no issuers found")
	}

	if !issuer.IsCA {
		return nil, fmt.Errorf("%s invalid ca basic constraints: is not ca", issuer.Subject)
	}
	return issuer, nil
}

func ocspStatusString(n int) string {
	switch n {
	case ocsp.Good:
		return "good"
	case ocsp.Revoked:
		return "revoked"
	default:
		return "unknown"
	}
}

func validOCSPResponse(r *ocsp.Response) error {
	// Time validation not handled by ParseResponse.
	// https://tools.ietf.org/html/rfc6960#section-4.2.2.1

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Replace the second bundle entry with the real intermediate CA cert
  2. Verify with `openssl x509 -in issuer.pem -text | grep 'CA:'` that it shows CA:TRUE
  3. Re-export the intermediate CA from the chain provided by your CA vendor

Example fix

// before
cat leaf.pem another-leaf.pem > bundle.pem
// after
cat leaf.pem intermediate-ca.pem > bundle.pem
# intermediate-ca.pem must contain Basic Constraints: CA:TRUE
Defensive patterns

Strategy: validation

Validate before calling

for _, c := range bundle[1:] {
    if !c.IsCA { return fmt.Errorf("%s is not a CA cert", c.Subject) }
}

Type guard

func isCA(c *x509.Certificate) bool { return c != nil && c.IsCA }

Prevention

When it happens

Trigger: The certificate found as issuer (from ca_file trust pool or bundle position 2) parses fine and matches, but has IsCA == false — e.g. a leaf/endpoint cert was supplied as the issuer.

Common situations: Operators copy the wrong cert into position 2 of the bundle (another leaf instead of the intermediate), or point ca_file at a server certificate instead of a CA cert.

Related errors


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