{"record":{"id":"b39ce967322ca444","repo":"decolua/9router","slug":"root-ca-not-found-start-server-first-to-generate","errorCode":null,"errorMessage":"Root CA not found. Start server first to generate it.","messagePattern":"Root CA not found\\. Start server first to generate it\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mitm/manager.js","lineNumber":848,"sourceCode":"  return { success: true };\n}\n\n/**\n * Disable DNS for a specific tool\n */\nasync function disableToolDNS(tool, sudoPassword) {\n  const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();\n  await removeDNSEntry(tool, password);\n  await saveDnsToolState(tool, false);\n  return { success: true };\n}\n\n/**\n * Install Root CA to system trust store (standalone, no server start)\n */\nasync function trustCert(sudoPassword) {\n  const rootCACertPath = path.join(MITM_DIR, \"rootCA.crt\");\n  if (!fs.existsSync(rootCACertPath)) throw new Error(\"Root CA not found. Start server first to generate it.\");\n  const { installCert } = require(\"./cert/install\");\n  if (!IS_WIN && !IS_MAC && !isSudoAvailable()) {\n    log(`🔐 Cert: system trust unavailable (no sudo). Use file: ${rootCACertPath}`);\n    return;\n  }\n  const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();\n  if (!password && isSudoPasswordRequired()) throw new Error(\"Sudo password required to trust certificate\");\n  await installCert(password, rootCACertPath);\n  if (password) setCachedPassword(password);\n}\n\n// Legacy aliases for backward compatibility\nconst startMitm = startServer;\nconst stopMitm = stopServer;\n\nmodule.exports = {\n  getMitmStatus,\n  startServer,","sourceCodeStart":830,"sourceCodeEnd":866,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/mitm/manager.js#L830-L866","documentation":"trustCert() installs the MITM root CA into the OS trust store, but the CA certificate is only generated when the MITM server starts. If MITM_DIR/rootCA.crt does not exist on disk, the function throws instead of installing a missing file. This forces the one-time server start that generates the certificate.","triggerScenarios":"Calling trustCert() on a machine where the MITM server has never been started, after manually deleting the MITM_DIR directory, or pointing the app at a fresh DATA_DIR/home directory.","commonSituations":"First-run setup where the user clicks 'Trust certificate' before ever starting the proxy; CI/container images with a wiped home dir; switching users so ~/.9router (or equivalent MITM_DIR) no longer holds rootCA.crt.","solutions":["Start the MITM server once (await startServer()) so rootCA.crt is generated in MITM_DIR","Verify the file exists: fs.existsSync(path.join(MITM_DIR, 'rootCA.crt'))","If MITM_DIR was wiped or moved, restart the server to regenerate the CA, then re-trust","On Linux without sudo, skip trustCert and manually trust the file printed in the log message"],"exampleFix":"// before\nawait trustCert(password);\n// after\nif (!fs.existsSync(path.join(MITM_DIR, \"rootCA.crt\"))) {\n  await startServer({ sudoPassword: password }); // generates rootCA.crt\n  await stopServer();\n}\nawait trustCert(password);","handlingStrategy":"validation","validationCode":"import fs from \"fs\";\nif (!fs.existsSync(path.join(MITM_DIR, \"rootCA.crt\"))) {\n  await startServer({}); // generates the CA\n}\nawait trustCert(sudoPassword);","typeGuard":"function hasRootCA(p) { return typeof p === \"string\" && fs.existsSync(p); }","tryCatchPattern":"try {\n  await trustCert(sudoPassword);\n} catch (err) {\n  if (err.message.includes(\"Root CA not found\")) {\n    await startServer({});\n    await trustCert(sudoPassword);\n  } else throw err;\n}","preventionTips":["Run the MITM server at least once before offering the 'trust certificate' action","Disable/grey out the trust button in the UI until rootCA.crt exists","Guard against wiping MITM_DIR; back up rootCA.crt across reinstalls","In containers/CI, mount or pre-generate the CA as part of setup"],"tags":["mitm","certificate","filesystem"],"backgroundTag":"root-ca-certificate-missing","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}