decolua/9router · error · Error

Failed to uninstall certificate

Error message

Failed to uninstall certificate

What it means

uninstallCertMac() computes the cert fingerprint and runs `security delete-certificate -Z <fp> /Library/Keychains/System.keychain` via sudo. Any failure of that command is rethrown as the fixed message 'Failed to uninstall certificate', discarding the underlying error detail.

Solutions

  1. Retry with the correct sudo password
  2. Check the cert exists: `security find-certificate -c 9router-root-ca /Library/Keychains/System.keychain`
  3. If already removed manually, treat as success and skip uninstall
  4. Manually run `security delete-certificate -Z <fingerprint> /Library/Keychains/System.keychain` to see the raw error
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the cert is present before attempting uninstall
const installed = await checkCertInstalled(certPath);
if (!installed) return; // nothing to uninstall, skip

Try / catch

try {
  await uninstallCert(sudoPassword, certPath);
} catch (e) {
  if (e.message === 'Failed to uninstall certificate') {
    // re-check; if already gone, treat as success
    if (!(await checkCertInstalled(certPath))) return;
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: uninstallCert() on macOS when: sudo password wrong or auth canceled, the cert is not present under that fingerprint, System.keychain is locked, or the terminal lacks permission to modify the keychain.

Common situations: Cert already removed manually (delete then fails or behaves unexpectedly); wrong sudo password; managed Mac blocking keychain modification; fingerprint mismatch because the CA was regenerated after install.

Understand the failure class

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/ffc5a3b0c321bdb2. Report an issue: GitHub.

Appendix: source

Thrown at src/mitm/cert/install.js:161

  }

  if (IS_WIN) {
    await uninstallCertWindows();
  } else if (IS_MAC) {
    await uninstallCertMac(sudoPassword, certPath);
  } else {
    await uninstallCertLinux(sudoPassword);
  }
}

async function uninstallCertMac(sudoPassword, certPath) {
  const fingerprint = getCertFingerprint(certPath).replace(/:/g, "");
  const command = `security delete-certificate -Z "${fingerprint}" /Library/Keychains/System.keychain`;
  try {
    await execWithPassword(command, sudoPassword);
    log("🔐 Cert: ✅ uninstalled from system keychain");
  } catch (err) {
    throw new Error("Failed to uninstall certificate");
  }
}

async function uninstallCertWindows() {
  // Auto-elevate via UAC popup if not admin
  const script = `certutil -delstore Root ${quotePs(ROOT_CA_CN)}`;
  try {
    await runElevatedPowerShell(script);
    log("🔐 Cert: ✅ uninstalled from Windows Root store");
  } catch (e) {
    throw new Error(`Failed to uninstall certificate: ${e.message}`);
  }
}

function checkCertInstalledLinux() {
  const config = getLinuxCertConfig();
  const certFile = `${config.dir}/9router-root-ca.crt`;
  return Promise.resolve(fs.existsSync(certFile));

View on GitHub (pinned to 90b52e06ff)