{"record":{"id":"f8bccc4e6efc0853","repo":"FiloSottile/mkcert","slug":"failed-enumerating-certs-v","errorCode":null,"errorMessage":"failed enumerating certs: %v","messagePattern":"failed enumerating certs: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"truststore_windows.go","lineNumber":118,"sourceCode":"\t)\n\tif ret != 0 {\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"failed adding cert: %v\", err)\n}\n\nfunc (w windowsRootStore) deleteCertsWithSerial(serial *big.Int) (bool, error) {\n\t// Go over each, deleting the ones we find\n\tvar cert *syscall.CertContext\n\tdeletedAny := false\n\tfor {\n\t\t// Next enum\n\t\tcertPtr, _, err := procCertEnumCertificatesInStore.Call(uintptr(w), uintptr(unsafe.Pointer(cert)))\n\t\tif cert = (*syscall.CertContext)(unsafe.Pointer(certPtr)); cert == nil {\n\t\t\tif errno, ok := err.(syscall.Errno); ok && errno == 0x80092004 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn deletedAny, fmt.Errorf(\"failed enumerating certs: %v\", err)\n\t\t}\n\t\t// Parse cert\n\t\tcertBytes := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:cert.Length]\n\t\tparsedCert, err := x509.ParseCertificate(certBytes)\n\t\t// We'll just ignore parse failures for now\n\t\tif err == nil && parsedCert.SerialNumber != nil && parsedCert.SerialNumber.Cmp(serial) == 0 {\n\t\t\t// Duplicate the context so it doesn't stop the enum when we delete it\n\t\t\tdupCertPtr, _, err := procCertDuplicateCertificateContext.Call(uintptr(unsafe.Pointer(cert)))\n\t\t\tif dupCertPtr == 0 {\n\t\t\t\treturn deletedAny, fmt.Errorf(\"failed duplicating context: %v\", err)\n\t\t\t}\n\t\t\tif ret, _, err := procCertDeleteCertificateFromStore.Call(dupCertPtr); ret == 0 {\n\t\t\t\treturn deletedAny, fmt.Errorf(\"failed deleting certificate: %v\", err)\n\t\t\t}\n\t\t\tdeletedAny = true\n\t\t}\n\t}\n\treturn deletedAny, nil","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/FiloSottile/mkcert/blob/1c1dc4ed27ed5936046b6398d39cab4d657a2d8e/truststore_windows.go#L100-L136","documentation":"During uninstall, mkcert loops CertEnumCertificatesInStore over the ROOT store; the expected loop exit is the CRYPT_E_NOT_FOUND errno 0x80092004 when enumeration finishes. Any other error while the returned context is NULL produces this message. In practice the store handle is bad (already closed) or an external actor (AV, concurrent cert-store modification) disrupted enumeration.","triggerScenarios":"`mkcert -uninstall` while another process concurrently modifies the ROOT store; the store handle being invalidated (service restart); AV/EDR software intercepting certificate-store enumeration; memory corruption of the CertContext pointer chain in unusual environments.","commonSituations":"CI jobs running mkcert uninstall concurrently with Windows Update or certutil store maintenance; security software on corporate laptops; running mkcert under Wine/Windows-compatibility layers where crypt32 semantics differ.","solutions":["Retry `mkcert -uninstall` once the machine is idle (no Windows Update / certutil activity).","Temporarily exclude the mkcert process in AV/EDR policy or coordinate with IT for a cert-store modification window.","Verify the store is readable: `certutil -store ROOT` — if this also fails, the store or profile is damaged; investigate that first.","As a manual fallback, delete the 'mkcert' entry via certmgr.msc or `certutil -delstore ROOT <serial>`."],"exampleFix":"# manual removal matching mkcert's serial-based delete\ncertutil -store ROOT | findstr /i mkcert\ncertutil -delstore ROOT <serial-from-output>","handlingStrategy":"retry","validationCode":"if out, err := exec.Command(\"certutil\", \"-store\", \"ROOT\").CombinedOutput(); err != nil {\n    log.Fatalf(\"ROOT store unreadable; fix store before uninstall: %s\", out)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Schedule uninstalls when Windows Update / certutil maintenance is not running.","Exclude mkcert from overzealous AV interception where policy allows.","Retry once after transient store errors before investigating deeper.","Keep `certutil -delstore ROOT <serial>` as a known manual fallback."],"tags":["mkcert","windows","crypt32","enumeration","certificate-store","uninstall"],"backgroundTag":null,"analyzedSha":"1c1dc4ed27ed5936046b6398d39cab4d657a2d8e","analyzedAt":"2026-08-15T09:28:09.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}