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

  1. Treat as non-fatal: the add/delete operation already completed; re-run `mkcert -check` or inspect the ROOT store to confirm the CA state.
  2. Ensure only one mkcert instance manipulates the store at a time to avoid handle races.
  3. Reboot (or restart the Cryptographic Services) if the store is in a bad state and retry.
  4. 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

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


AI-assisted analysis of FiloSottile/mkcert@1c1dc4ed27 (2026-08-15). Data as JSON: /api/errors/b6ce976c0564134e. Report an issue: GitHub.