nats-io/nats-server · error
NCryptOpenStorageProvider returned %X: %v
Error message
NCryptOpenStorageProvider returned %X: %v
What it means
NCryptOpenStorageProvider failed to open the requested Windows key storage provider (e.g. the CNG 'Microsoft Software Key Storage Provider' or a TPM/smartcard provider). The NATS server calls NCryptOpenStorageProvider via syscall when opening the certificate store for TLS client-cert auth; the returned NTSTATUS (r) and the Go syscall error are wrapped into this message. Without a provider handle the server cannot enumerate certificates, so key-store-backed TLS identity setup fails.
Source
Thrown at server/certstore/certstore_windows.go:316
// winWide returns a pointer to uint16 representing the equivalent
// to a Windows LPCWSTR.
func winWide(s string) *uint16 {
w := utf16.Encode([]rune(s))
w = append(w, 0)
return &w[0]
}
// winOpenProvider gets a provider handle for subsequent calls
func winOpenProvider(provider string) (uintptr, error) {
var hProv uintptr
pname := winWide(provider)
// Open the provider, the last parameter is not used
r, _, err := winNCryptOpenStorageProvider.Call(uintptr(unsafe.Pointer(&hProv)), uintptr(unsafe.Pointer(pname)), 0)
if r == 0 {
return hProv, nil
}
return hProv, fmt.Errorf("NCryptOpenStorageProvider returned %X: %v", r, err)
}
// winFindCert wraps the CertFindCertificateInStore library call. Note that any cert context passed
// into prev will be freed. If no certificate was found, nil will be returned.
func winFindCert(store windows.Handle, enc, findFlags, findType uint32, para *uint16, prev *windows.CertContext) (*windows.CertContext, error) {
h, _, err := winCertFindCertificateInStore.Call(
uintptr(store),
uintptr(enc),
uintptr(findFlags),
uintptr(findType),
uintptr(unsafe.Pointer(para)),
uintptr(unsafe.Pointer(prev)),
)
if h == 0 {
// Actual error, or simply not found?
if errno, ok := err.(syscall.Errno); ok && errno == syscall.Errno(winCryptENotFound) {
return nil, ErrFailedCertSearch
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Check the %X NTSTATUS in the message and look it up (e.g. 0x80090016 = NTE_BAD_KEYSET: keyset does not exist).
- Verify the provider name in your TLS config matches an installed provider (certutil -csplist or ncrypt providers list).
- Ensure the account running the NATS server (LocalSystem/service account) has access to the required key store; key stores are per-user.
- If the keyset is corrupt, recreate the certificate/key pair or import the PFX into the target store with certlm.msc/certutil.
- Ensure required services (TPM service, smartcard service) are running when using hardware providers.
Example fix
// before opts.TLSConfig.CertStore = "Microsoft Sofware Key Storage Provider" // typo // after opts.TLSConfig.CertStore = "Microsoft Software Key Storage Provider"
Defensive patterns
Strategy: fallback
Validate before calling
// PowerShell: verify the provider exists before configuring the server certutil -csplist | Select-String "Provider Name"
Try / catch
if err := server.Start(); err != nil && strings.Contains(err.Error(), "NCryptOpenStorageProvider") {
// parse NTSTATUS %X, log actionable message, and fall back to a PEM-file TLS config
log.Fatalf("key store unavailable (%v); use cert_file/key_file instead", err)
} Prevention
- Run certutil -csplist to confirm the provider name before configuring it.
- Give the service account access to the key store or use machine store certificates.
- Keep TLS config with PEM file fallback so server can start without the CNG provider.
- Check TPM/smartcard service health on hosts using hardware providers.
When it happens
Trigger: Calling winOpenProvider (via winOpenCertStore during NATS startup with a certstore-based TLS config on Windows) when: the provider name string is misspelled or not installed, the key store service is unavailable, or NCryptOpenStorageProvider returns a nonzero NTSTATUS (e.g. NTE_BAD_KEYSET 0x80090016, NTE_PROV_TYPE_NOT_DEF).
Common situations: Windows machine with corrupted or missing key containers; requesting a TPM or smartcard provider whose driver/service is not running; running as a service account without access to the user key store; typo in the configured provider name.
Related errors
- unable to find certificate in store
- invalid chain link
- no available OCSP servers
- ErrBadCryptoStoreProvider
- ErrBadRSAHashAlgorithm
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/1c2718d04e3eb30b.
Report an issue: GitHub.