microsoft/playwright · error · Error
clientCertificates for origin
Error message
clientCertificates for origin "${origin}" mix noCertificate with a real certificate What it means
SocksClientCertificatesInterceptor builds one TLS secure context per origin. If some clientCertificates entries for an origin have noCertificate=true and others carry real certificate material, the interceptor cannot decide whether to require or bypass client auth for that origin and throws during construction.
Solutions
- Ensure all clientCertificates entries for a given origin are consistent: either all noCertificate or all carry real certificates.
- Remove the redundant noCertificate entry if the origin should use client certs.
- Deduplicate entries per origin after merging configuration from multiple sources.
Example fix
// before
clientCertificates: [
{ origin: 'https://api.example.com', noCertificate: true },
{ origin: 'https://api.example.com', cert: './c.pem', key: './k.pem' }
]
// after
clientCertificates: [
{ origin: 'https://api.example.com', cert: './c.pem', key: './k.pem' }
] Defensive patterns
Strategy: validation
Validate before calling
const byOrigin = new Map();
for (const c of clientCertificates) {
const list = byOrigin.get(c.origin) ?? [];
list.push(!!c.noCertificate);
byOrigin.set(c.origin, list);
}
for (const [origin, flags] of byOrigin) {
if (flags.some(Boolean) && flags.some(f => !f))
throw new Error(`Mixed noCertificate entries for ${origin}`);
} Type guard
null
Try / catch
null
Prevention
- Normalize clientCertificates per origin right after config merge, before context creation.
- Pin one policy (certs or noCertificate) per origin in your config schema.
When it happens
Trigger: Configuring multiple clientCertificates entries for the same origin where at least one has noCertificate: true and at least one has cert/key/pfx — e.g. [{ origin: 'https://api.example.com', noCertificate: true }, { origin: 'https://api.example.com', cert: '...', key: '...' }].
Common situations: Test config merging (e.g. projects with different cert options concatenated) producing mixed entries for a shared origin; environment-specific overrides adding a noCertificate entry alongside the base cert entry.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- noCertificate is set together with cert, key, passphrase or…
- cert is specified without key
- clientCertificates.origin is required
- key is specified without cert
- None of cert, key, passphrase or pfx is specified
AI-assisted analysis of microsoft/playwright@500c9c822c (2026-09-15).
Data as JSON: /api/errors/251dc3a4ae5f263e.
Report an issue: GitHub.
Appendix: source
Thrown at packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts:337
if (proxyFromEnv)
return createProxyAgent({ server: proxyFromEnv });
}
_initSecureContexts(clientCertificates: types.BrowserContextOptions['clientCertificates']) {
// Step 1. Group certificates by origin.
const origin2certs = new Map<string, NonNullable<types.BrowserContextOptions['clientCertificates']>>();
for (const cert of clientCertificates || []) {
const origin = normalizeOrigin(cert.origin);
const certs = origin2certs.get(origin) || [];
certs.push(cert);
origin2certs.set(origin, certs);
}
// Step 2. Create secure contexts for each origin.
for (const [origin, certs] of origin2certs) {
const noCertificateCount = certs.filter(cert => cert.noCertificate).length;
if (noCertificateCount > 0 && noCertificateCount < certs.length)
throw new Error(`clientCertificates for origin "${origin}" mix noCertificate with a real certificate`);
if (noCertificateCount > 0) {
this.secureContextMap.set(origin, undefined);
continue;
}
try {
this.secureContextMap.set(origin, tls.createSecureContext(convertClientCertificatesToTLSOptions(certs)));
} catch (error) {
error = rewriteOpenSSLErrorIfNeeded(error);
throw rewriteErrorMessage(error, `Failed to load client certificate: ${error.message}`);
}
}
}
public static async create(progress: Progress, contextOptions: Pick<types.BrowserContextOptions, 'clientCertificates' | 'ignoreHTTPSErrors' | 'proxy'>) {
const proxy = new ClientCertificatesProxy(contextOptions);
try {
await progress.race(proxy._socksProxy.listen(0, '127.0.0.1'));
return proxy;View on GitHub (pinned to 500c9c822c)