microsoft/playwright · error · Error

None of cert, key, passphrase or pfx is specified

Error message

None of cert, key, passphrase or pfx is specified

What it means

Thrown by verifyClientCertificates() while validating each entry in context options clientCertificates. A certificate entry must carry real credential material: it throws when an entry has an origin but none of cert, key, passphrase, or pfx is set. Playwright validates up front so the TLS proxy it spins up (ClientCertificatesProxy) does not receive an unusable entry.

Source

Thrown at packages/playwright-core/src/server/browserContext.ts:802

    return;
  geolocation.accuracy = geolocation.accuracy || 0;
  const { longitude, latitude, accuracy } = geolocation;
  if (longitude < -180 || longitude > 180)
    throw new Error(`geolocation.longitude: precondition -180 <= LONGITUDE <= 180 failed.`);
  if (latitude < -90 || latitude > 90)
    throw new Error(`geolocation.latitude: precondition -90 <= LATITUDE <= 90 failed.`);
  if (accuracy < 0)
    throw new Error(`geolocation.accuracy: precondition 0 <= ACCURACY failed.`);
}

export function verifyClientCertificates(clientCertificates?: types.BrowserContextOptions['clientCertificates']) {
  if (!clientCertificates)
    return;
  for (const cert of clientCertificates) {
    if (!cert.origin)
      throw new Error(`clientCertificates.origin is required`);
    if (!cert.cert && !cert.key && !cert.passphrase && !cert.pfx)
      throw new Error('None of cert, key, passphrase or pfx is specified');
    if (cert.cert && !cert.key)
      throw new Error('cert is specified without key');
    if (!cert.cert && cert.key)
      throw new Error('key is specified without cert');
    if (cert.pfx && (cert.cert || cert.key))
      throw new Error('pfx is specified together with cert, key or passphrase');
  }
}

export function normalizeProxySettings(proxy: types.ProxySettings): types.ProxySettings {
  let { server, bypass } = proxy;
  let url;
  try {
    // new URL('127.0.0.1:8080') throws
    // new URL('localhost:8080') fails to parse host or protocol
    // In both of these cases, we need to try re-parse URL with `http://` prefix.
    url = new URL(server);
    if (!url.host || !url.protocol)

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Provide a cert/key pair (cert + key Buffers, or rely on certPath/keyPath which are read into Buffers beforehand) OR a pfx bundle (optionally with passphrase).
  2. Verify the entry shape against the ClientCertificate type: { origin, cert?, key?, pfx?, passphrase? }.
  3. Remove the entry entirely if no credentials are needed for that origin.

Example fix

// before
await browser.newContext({
  clientCertificates: [{ origin: 'https://example.com' }],
});
// after
import fs from 'fs';
await browser.newContext({
  clientCertificates: [{
    origin: 'https://example.com',
    cert: fs.readFileSync('./client.crt'),
    key: fs.readFileSync('./client.key'),
  }],
});
Defensive patterns

Strategy: validation

Validate before calling

import type { ClientCertificate } from 'playwright-core';
function validateClientCerts(certs?: ClientCertificate[]) {
  if (!certs) return;
  for (const c of certs) {
    if (!c.origin) throw new Error('clientCertificates.origin is required');
    if (!c.cert && !c.key && !c.passphrase && !c.pfx)
      throw new Error(`No cert material for ${c.origin}: provide cert+key, or pfx (+passphrase)`);
  }
}
// call before browser.newContext / APIRequestContext.newContext

Type guard

function hasCertMaterial(c: ClientCertificate): boolean {
  return !!(c.cert || c.key || c.passphrase || c.pfx);
}

Prevention

When it happens

Trigger: Calling browser.newContext({ clientCertificates: [{ origin: 'https://example.com' }] }) — origin supplied but no cert/key/pfx/passphrase fields. Also triggered via APIRequestContext.newContext with the same shape, or launchPersistentContext with clientCertificates.

Common situations: Developer adds a clientCertificates entry planning to fill credentials later but forgets. Passing only certPath/keyPath as strings while the validation runs against cert/key Buffer fields before conversion (note: conversion happens earlier in toClientCertificatesProtocol, but a fully empty entry still passes through). Confusing passphrase-only intent.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/9970ba84d22b0ab9. Report an issue: GitHub.