FiloSottile/mkcert · warning
no certs found
Error message
no certs found
What it means
mkcert's uninstall path walks the Windows ROOT system store and deletes every certificate whose serial number equals the local CA's serial. If the enumeration completes but nothing matched, it synthesizes 'no certs found' and fatalIfErr terminates. It almost always means the CA was never installed on this machine, was already uninstalled, or the CA (and thus its serial number) changed since installation.
Source
Thrown at truststore_windows.go:63
// Open root store
store, err := openWindowsRootStore()
fatalIfErr(err, "open root store")
defer store.close()
// Add cert
fatalIfErr(store.addCert(cert), "add cert")
return true
}
func (m *mkcert) uninstallPlatform() bool {
// We'll just remove all certs with the same serial number
// Open root store
store, err := openWindowsRootStore()
fatalIfErr(err, "open root store")
defer store.close()
// Do the deletion
deletedAny, err := store.deleteCertsWithSerial(m.caCert.SerialNumber)
if err == nil && !deletedAny {
err = fmt.Errorf("no certs found")
}
fatalIfErr(err, "delete cert")
return true
}
type windowsRootStore uintptr
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)
}View on GitHub (pinned to 1c1dc4ed27)
Solutions
- If the goal is simply a clean store, treat this as success: the CA is not present, nothing to remove.
- Check the Windows ROOT store (certmgr.msc -> Trusted Root Certification Authorities) for a leftover 'mkcert developed by FiloSottile' entry and delete it manually if the serial changed.
- If a genuine stale entry with a different serial exists, rerun `mkcert -install` with the original CAROOT first so the serials match, then `mkcert -uninstall`.
- In scripted cleanup, guard the call: only uninstall when an install previously succeeded in the same run.
Example fix
// before: unconditional cleanup fails on fresh machines mkcert -uninstall // after: only uninstall if this run installed it if [ "$INSTALLED_MKCERT" = "1" ]; then mkcert -uninstall; fi
Defensive patterns
Strategy: validation
Validate before calling
out, err := exec.Command("certutil", "-store", "ROOT").CombinedOutput()
if err == nil && !strings.Contains(string(out), "mkcert") {
// nothing to uninstall; skip `mkcert -uninstall`
return nil
} Prevention
- Make uninstall idempotent in scripts: check the store (or your own install marker) before calling `mkcert -uninstall`.
- Keep CAROOT stable between install and uninstall so serials always match.
- Run uninstall only in sessions that performed a successful install.
- Remember a second uninstall after success is expected to report 'no certs found'.
When it happens
Trigger: Running `mkcert -uninstall` when `mkcert -install` never ran on this host; running it a second time after a successful uninstall; deleting CAROOT and letting mkcert generate a fresh CA (new serial) before uninstalling, so the old store entry's serial no longer matches.
Common situations: CI or container images that blindly run `mkcert -uninstall` in a cleanup step; sharing/syncing a CAROOT between machines so serials diverge from what is actually in each machine's store; a teammate resetting CAROOT then trying to clean up the old install.
Related errors
- failed enumerating certs: %v
- failed deleting certificate: %v
- failed to open windows root store: %v
- failed duplicating context: %v
- invalid PEM data
AI-assisted analysis of FiloSottile/mkcert@1c1dc4ed27 (2026-08-15).
Data as JSON: /api/errors/b62f9a6832acf056.
Report an issue: GitHub.