{"record":{"id":"0a443804233aa463","repo":"FiloSottile/mkcert","slug":"failed-duplicating-context-v","errorCode":null,"errorMessage":"failed duplicating context: %v","messagePattern":"failed duplicating context: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"truststore_windows.go","lineNumber":128,"sourceCode":"\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\n}\n","sourceCodeStart":110,"sourceCodeEnd":138,"githubUrl":"https://github.com/FiloSottile/mkcert/blob/1c1dc4ed27ed5936046b6398d39cab4d657a2d8e/truststore_windows.go#L110-L138","documentation":"Before deleting a matched certificate, mkcert duplicates its context with CertDuplicateCertificateContext so the enumeration continues past the deletion; a NULL return triggers this error. Duplicate merely increments a reference count on an existing context, so failure implies an invalid context pointer — the enum returned a context that was freed or corrupted between the call and the duplication.","triggerScenarios":"`mkcert -uninstall` when the enumerated CERT_CONTEXT becomes invalid mid-loop (concurrent deletion by another process), or under memory corruption / non-Windows compatibility layers where the CertContext pointer chain is unreliable. Extremely rare on healthy systems.","commonSituations":"Two mkcert uninstalls racing; an EDR agent deleting certs while mkcert enumerates; running under Wine or translation layers with incomplete crypt32 support.","solutions":["Ensure only one process manipulates the ROOT store at a time; retry `mkcert -uninstall`.","Reboot to clear any wedged store state and retry.","Remove the mkcert CA manually with certmgr.msc or `certutil -delstore ROOT <serial>`.","If it reproduces consistently, capture the GetLastError value and report upstream to mkcert."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never run two mkcert install/uninstall operations concurrently.","Avoid running mkcert's store operations under Wine/compatibility layers.","Retry the uninstall after any concurrent cert-store churn settles.","Report reproducible cases upstream with GetLastError details."],"tags":["mkcert","windows","crypt32","cert-context","race-condition","uninstall"],"backgroundTag":null,"analyzedSha":"1c1dc4ed27ed5936046b6398d39cab4d657a2d8e","analyzedAt":"2026-08-15T09:28:09.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}