{"record":{"id":"d0e4149fb0705020","repo":"microsoft/playwright","slug":"cert-is-specified-without-key","errorCode":null,"errorMessage":"cert is specified without key","messagePattern":"cert is specified without key","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/browserContext.ts","lineNumber":804,"sourceCode":"  const { longitude, latitude, accuracy } = geolocation;\n  if (longitude < -180 || longitude > 180)\n    throw new Error(`geolocation.longitude: precondition -180 <= LONGITUDE <= 180 failed.`);\n  if (latitude < -90 || latitude > 90)\n    throw new Error(`geolocation.latitude: precondition -90 <= LATITUDE <= 90 failed.`);\n  if (accuracy < 0)\n    throw new Error(`geolocation.accuracy: precondition 0 <= ACCURACY failed.`);\n}\n\nexport function verifyClientCertificates(clientCertificates?: types.BrowserContextOptions['clientCertificates']) {\n  if (!clientCertificates)\n    return;\n  for (const cert of clientCertificates) {\n    if (!cert.origin)\n      throw new Error(`clientCertificates.origin is required`);\n    if (!cert.cert && !cert.key && !cert.passphrase && !cert.pfx)\n      throw new Error('None of cert, key, passphrase or pfx is specified');\n    if (cert.cert && !cert.key)\n      throw new Error('cert is specified without key');\n    if (!cert.cert && cert.key)\n      throw new Error('key is specified without cert');\n    if (cert.pfx && (cert.cert || cert.key))\n      throw new Error('pfx is specified together with cert, key or passphrase');\n  }\n}\n\nexport function normalizeProxySettings(proxy: types.ProxySettings): types.ProxySettings {\n  let { server, bypass } = proxy;\n  let url;\n  try {\n    // new URL('127.0.0.1:8080') throws\n    // new URL('localhost:8080') fails to parse host or protocol\n    // In both of these cases, we need to try re-parse URL with `http://` prefix.\n    url = new URL(server);\n    if (!url.host || !url.protocol)\n      url = new URL('http://' + server);\n  } catch (e) {","sourceCodeStart":786,"sourceCodeEnd":822,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/browserContext.ts#L786-L822","documentation":"Thrown by verifyClientCertificates() when a clientCertificates entry has cert set but key is falsy. X.509 client auth requires both halves of the key pair, so Playwright rejects an asymmetric entry before building the TLS secure context.","triggerScenarios":"browser.newContext({ clientCertificates: [{ origin, cert: <Buffer>, /* key missing */ }] }) or the equivalent via APIRequestContext.newContext / launchPersistentContext.","commonSituations":"Developer pastes the certificate buffer but forgets the private key, or sets keyPath to a wrong/empty path that resolved to undefined.","solutions":["Supply key alongside cert (key: fs.readFileSync('./client.key') or keyPath resolved correctly).","If you only have a bundled file, split it into cert and key, or use the pfx form instead and remove cert/key.","Double-check that keyPath points to an existing readable file so the Buffer is populated before validation."],"exampleFix":"// before\nclientCertificates: [{ origin, cert: fs.readFileSync('client.crt') }]\n// after\nclientCertificates: [{ origin, cert: fs.readFileSync('client.crt'), key: fs.readFileSync('client.key') }]","handlingStrategy":"validation","validationCode":"function validateCertKeyPair(certs?: ClientCertificate[]) {\n  for (const c of certs || []) {\n    if (c.cert && !c.key) throw new Error(`cert set without key for ${c.origin}`);\n  }\n}","typeGuard":"function isCompleteCertKeyPair(c: ClientCertificate): boolean {\n  return (!!c.cert && !!c.key) || (!c.cert && !c.key);\n}","tryCatchPattern":null,"preventionTips":["Load cert and key from a single config block so they stay in sync.","Write a unit test asserting every clientCertificates entry passes verifyClientCertificates semantics."],"tags":["client-certificates","tls","validation"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}