TechnitiumSoftware/DnsServer · error · ArgumentException

Web Service TLS certificate file must contain a certificate

Error message

Web Service TLS certificate file must contain a certificate with private key.

What it means

ArgumentException thrown by LoadWebServiceTlsCertificate when none of the certificates in the loaded PKCS #12 collection has a private key. The loader scans the collection for a cert with HasPrivateKey; without one the server cannot present a TLS endpoint, so it aborts.

Source

Thrown at DnsServerCore/DnsWebService.cs:2710

                default:
                    throw new ArgumentException("Web Service TLS certificate file must be PKCS #12 formatted with .pfx or .p12 extension: " + tlsCertificatePath);
            }

            X509Certificate2Collection certificateCollection = X509CertificateLoader.LoadPkcs12CollectionFromFile(tlsCertificatePath, tlsCertificatePassword, X509KeyStorageFlags.PersistKeySet);
            X509Certificate2 serverCertificate = null;

            foreach (X509Certificate2 certificate in certificateCollection)
            {
                if (certificate.HasPrivateKey)
                {
                    serverCertificate = certificate;
                    break;
                }
            }

            if (serverCertificate is null)
                throw new ArgumentException("Web Service TLS certificate file must contain a certificate with private key.");

            List<SslApplicationProtocol> applicationProtocols = new List<SslApplicationProtocol>();

            if (_webServiceEnableHttp3)
                applicationProtocols.Add(new SslApplicationProtocol("h3"));

            if (IsHttp2Supported())
                applicationProtocols.Add(new SslApplicationProtocol("h2"));

            applicationProtocols.Add(new SslApplicationProtocol("http/1.1"));

            _webServiceSslServerAuthenticationOptions = new SslServerAuthenticationOptions
            {
                ApplicationProtocols = applicationProtocols,
                ServerCertificateContext = SslStreamCertificateContext.Create(serverCertificate, certificateCollection, false)
            };

            _webServiceCertificateLastModifiedOn = fileInfo.LastWriteTimeUtc;

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Re-export the PFX including the private key (mark key as exportable) from the source store/CA.
  2. Verify with openssl: 'openssl pkcs12 -in cert.pfx -info -noout' should list a private key.
  3. Re-issue/renew the certificate with an exportable private key if the key is non-exportable.

Example fix

# re-export including the private key
openssl pkcs12 -export -in server.crt -inkey server.key -out server.pfx
# verify a private key is present
openssl pkcs12 -in server.pfx -info -noout -passin pass:****
Defensive patterns

Strategy: validation

Validate before calling

using var coll = new X509Certificate2Collection();
coll.Import(webServiceTlsCertificatePath, password, X509KeyStorageFlags.DefaultKeySet);
bool hasPrivate = coll.Cast<X509Certificate2>().Any(c => c.HasPrivateKey);
if (!hasPrivate)
    throw new ArgumentException("PFX must contain a certificate with a private key.");

Type guard

static bool PfxHasPrivateKey(string path, string password)
{
    var coll = new X509Certificate2Collection();
    coll.Import(path, password, X509KeyStorageFlags.DefaultKeySet);
    return coll.Cast<X509Certificate2>().Any(c => c.HasPrivateKey);
}

Try / catch

null

Prevention

When it happens

Trigger: Supplying a .pfx/.p12 that contains only public certificates (e.g. a CA chain) and no end-entity certificate with its private key, or a bundle where the private key was not exported.

Common situations: Exported the PFX without checking 'include private key'; exported only the chain; password-protected bundle opened but key absent; cert renewed and only public part re-bundled.

Understand the failure class

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/a41da2c21b96554c. Report an issue: GitHub.