FiloSottile/mkcert · warning
failed to close windows root store: %v
Error message
failed to close windows root store: %v
What it means
After installing or uninstalling, mkcert closes the ROOT store handle with CertCloseStore(handle, 0); if the API returns 0 the formatted error is returned. Because the handle is closed via `defer store.close()` after the operation already succeeded, this failure is cosmetic — the store mutation completed but the handle teardown failed (typically a handle/allocation issue or the store already closed). mkcert does not call fatalIfErr on this path's result in the defer, so impact is limited to resource hygiene.
Source
Thrown at truststore_windows.go:88
func openWindowsRootStore() (windowsRootStore, error) {
rootStr, err := syscall.UTF16PtrFromString("ROOT")
if err != nil {
return 0, err
}
store, _, err := procCertOpenSystemStoreW.Call(0, uintptr(unsafe.Pointer(rootStr)))
if store != 0 {
return windowsRootStore(store), nil
}
return 0, fmt.Errorf("failed to open windows root store: %v", err)
}
func (w windowsRootStore) close() error {
ret, _, err := procCertCloseStore.Call(uintptr(w), 0)
if ret != 0 {
return nil
}
return fmt.Errorf("failed to close windows root store: %v", err)
}
func (w windowsRootStore) addCert(cert []byte) error {
// TODO: ok to always overwrite?
ret, _, err := procCertAddEncodedCertificateToStore.Call(
uintptr(w), // HCERTSTORE hCertStore
uintptr(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING), // DWORD dwCertEncodingType
uintptr(unsafe.Pointer(&cert[0])), // const BYTE *pbCertEncoded
uintptr(len(cert)), // DWORD cbCertEncoded
3, // DWORD dwAddDisposition (CERT_STORE_ADD_REPLACE_EXISTING is 3)
0, // PCCERT_CONTEXT *ppCertContext
)
if ret != 0 {
return nil
}
return fmt.Errorf("failed adding cert: %v", err)
}
View on GitHub (pinned to 1c1dc4ed27)
Solutions
- Treat as non-fatal: the add/delete operation already completed; re-run `mkcert -check` or inspect the ROOT store to confirm the CA state.
- Ensure only one mkcert instance manipulates the store at a time to avoid handle races.
- Reboot (or restart the Cryptographic Services) if the store is in a bad state and retry.
- If reproducible, report upstream to the mkcert project with the GetLastError value.
Defensive patterns
Strategy: try-catch
Try / catch
if err := store.close(); err != nil {
// operation already succeeded; log and continue, do not fail the run
log.Printf("warning: store close failed: %v", err)
} Prevention
- Serialize store access: one mkcert process at a time.
- Close each store handle exactly once and right after use.
- Treat close failures as hygiene warnings, not transactional failures — verify outcomes with `mkcert -CAROOT`/store inspection instead.
When it happens
Trigger: CertCloseStore returning FALSE because the handle is invalid or was already closed; internal cert-context leaks making close fail; running on a Windows version where the store was invalidated between open and close (e.g. store service restarted mid-operation).
Common situations: Rare in practice; occasionally observed after AV interference with crypt32 or in long-lived processes that manipulate the store repeatedly; mostly seen when the same store handle is closed twice due to upstream code changes.
Related errors
- failed to open windows root store: %v
- failed adding cert: %v
- failed enumerating certs: %v
- failed duplicating context: %v
- failed deleting certificate: %v
AI-assisted analysis of FiloSottile/mkcert@1c1dc4ed27 (2026-08-15).
Data as JSON: /api/errors/b6ce976c0564134e.
Report an issue: GitHub.