nats-io/nats-server · error

'cert_file' and 'cert_store' may not both be configured

Error message

'cert_file' and 'cert_store' may not both be configured

What it means

ErrConflictCertFileAndStore is a configuration validation error: TLS options may not specify both cert_file (file-based certificate) and cert_store (Windows store-based certificate), since the two mechanisms are mutually exclusive ways to supply the serving certificate.

Source

Thrown at server/certstore/errors.go:60

	ErrExtractPropertyFromKey = errors.New("unable to extract property from key")

	// ErrBadECCCurveName represents an ECC signature curve name that is bad or unsupported
	ErrBadECCCurveName = errors.New("unsupported ECC curve name")

	// ErrFailedCertSearch represents not able to find certificate in store
	ErrFailedCertSearch = errors.New("unable to find certificate in store")

	// ErrFailedX509Extract represents not being able to extract x509 certificate from found cert in store
	ErrFailedX509Extract = errors.New("unable to extract x509 from certificate")

	// ErrBadMatchByType represents unknown CERT_MATCH_BY passed
	ErrBadMatchByType = errors.New("cert match by type not implemented")

	// ErrBadCertStore represents unknown CERT_STORE passed
	ErrBadCertStore = errors.New("cert store type not implemented")

	// ErrConflictCertFileAndStore represents ambiguous configuration of both file and store
	ErrConflictCertFileAndStore = errors.New("'cert_file' and 'cert_store' may not both be configured")

	// ErrBadCertStoreField represents malformed cert_store option
	ErrBadCertStoreField = errors.New("expected 'cert_store' to be a valid non-empty string")

	// ErrBadCertMatchByField represents malformed cert_match_by option
	ErrBadCertMatchByField = errors.New("expected 'cert_match_by' to be a valid non-empty string")

	// ErrBadCertMatchField represents malformed cert_match option
	ErrBadCertMatchField = errors.New("expected 'cert_match' to be a valid non-empty string")

	// ErrBadCaCertMatchField represents malformed cert_match option
	ErrBadCaCertMatchField = errors.New("expected 'ca_certs_match' to be a valid non-empty string array")

	// ErrBadCertMatchSkipInvalidField represents malformed cert_match_skip_invalid option
	ErrBadCertMatchSkipInvalidField = errors.New("expected 'cert_match_skip_invalid' to be a boolean")

	// ErrOSNotCompatCertStore represents cert_store passed that exists but is not valid on current OS
	ErrOSNotCompatCertStore = errors.New("cert_store not compatible with current operating system")

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Remove the cert_file (and key_file) entries if you intend store-based certs, keeping only cert_store/cert_match_by/cert_match.
  2. Alternatively remove cert_store if you intend file-based TLS.
  3. For CA trust material remember ca_file and ca_store have analogous exclusivity — keep each TLS block consistent.
  4. Search the config (and any includes/flag overrides) for both keys being set on the same block.

Example fix

// before
tls {
  cert_file: "./cert.pem"
  cert_store: "LocalMachine\\My"
}
// after
tls {
  cert_store: "LocalMachine\\My"
  cert_match_by: "thumbprint"
  cert_match: "AB12..."
}
Defensive patterns

Strategy: validation

Validate before calling

if cfg.TLS.CertFile != "" && cfg.TLS.CertStore != "" {
    return errors.New("cert_file and cert_store are mutually exclusive")
}

Type guard

func isConflictCertFileAndStore(err error) bool { return errors.Is(err, certstore.ErrConflictCertFileAndStore) }

Try / catch

opts, err := server.ProcessOptions(...)
if err != nil && strings.Contains(err.Error(), "may not both be configured") {
    // strip one of cert_file/cert_store from config
}

Prevention

When it happens

Trigger: server/opts.go:5833 — ProcessOptions/TLS validation returns it when tc.CertFile is non-empty AND tc.CertStore is non-empty in the same tls/remote/cluster TLS config block.

Common situations: Merging config fragments where one team added cert_file and another enabled Windows store support, or converting a config from file-based to store-based and leaving the old cert_file line in place.

Related errors


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