{"record":{"id":"91530d1530da467a","repo":"facebook/docusaurus","slug":"the-certificate-path-cert-path-and-key-path-k","errorCode":null,"errorMessage":"The certificate path=${cert.path} and key path=${key.path} do not match.","messagePattern":"The certificate path=(.+?) and key path=(.+?) do not match\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus/src/webpack/utils/getHttpsConfig.ts","lineNumber":41,"sourceCode":"  } catch (error) {\n    throw new Error(\n      logger.interpolate`The certificate path=${cert.path} is invalid.`,\n      {cause: error},\n    );\n  }\n\n  let keyPublicKey: crypto.KeyObject;\n  try {\n    keyPublicKey = crypto.createPublicKey(crypto.createPrivateKey(key.content));\n  } catch (error) {\n    throw new Error(\n      logger.interpolate`The certificate key path=${key.path} is invalid.`,\n      {cause: error},\n    );\n  }\n\n  if (!certPublicKey.equals(keyPublicKey)) {\n    throw new Error(\n      logger.interpolate`The certificate path=${cert.path} and key path=${key.path} do not match.`,\n    );\n  }\n}\n\ntype HttpsConfigOptions = {\n  https: boolean;\n  sslCert: string;\n  sslKey: string;\n};\n\nfunction getExplicitHttps(\n  options: Partial<HttpsConfigOptions>,\n): boolean | undefined {\n  return (\n    options.https ??\n    (typeof process.env.DOCUSAURUS_HTTPS !== 'undefined'\n      ? process.env.DOCUSAURUS_HTTPS == 'true'","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus/src/webpack/utils/getHttpsConfig.ts#L23-L59","documentation":"Thrown by `validateKeyAndCerts` when both the certificate and the private key parse successfully but their embedded public keys do not match — i.e. the cert and key are not a pair. This catches the common mistake of mixing files from different cert generations.","triggerScenarios":"Providing a cert and key that were generated separately and don't correspond. After both parse, the check `!certPublicKey.equals(keyPublicKey)` at getHttpsConfig.ts:40-45 fires.","commonSituations":"Regenerating a cert and forgetting to update the key (or vice versa); mixing files from two `mkcert`/`openssl` runs; copying the wrong pair from a secrets folder.","solutions":["Regenerate a matched cert+key pair together (`mkcert localhost` produces both).","Verify the match: `diff <(openssl x509 -in cert.pem -pubkey -noout) <(openssl pkey -in key.pem -pubout)`.","Point `sslCert` and `sslKey` at the corresponding files from the same generation."],"exampleFix":"# before (mismatched pair from two runs)\nsslCert: ./cert-run-1.pem\nsslKey:  ./key-run-2.pem\n# after (regenerate together)\n#   mkcert localhost\nsslCert: ./localhost.pem\nsslKey:  ./localhost-key.pem","handlingStrategy":"validation","validationCode":"const crypto = require('crypto');\nconst fs = require('fs');\nfunction certMatchesKey(certPath: string, keyPath: string) {\n  const cert = new crypto.X509Certificate(fs.readFileSync(certPath));\n  const key = crypto.createPublicKey(crypto.createPrivateKey(fs.readFileSync(keyPath)));\n  return cert.publicKey.equals(key);\n}","typeGuard":null,"tryCatchPattern":"try {\n  validateKeyAndCerts({cert, key});\n} catch (e) {\n  if (/do not match/.test(e.message)) {\n    console.error('Cert and key are not a pair — regenerate together');\n  }\n  throw e;\n}","preventionTips":["Generate cert+key as a pair (`mkcert localhost`) and never mix files from different runs.","Verify the match with `diff <(openssl x509 -in cert.pem -pubkey -noout) <(openssl pkey -in key.pem -pubout)`.","Store the pair together (e.g. in one secrets folder) and reference by absolute paths."],"tags":["https","ssl","dev-server","config","cert-matching"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}