TechnitiumSoftware/DnsServer · error · ArgumentException

Web server '{_name}' TLS certificate file must contain a cer

Error message

Web server '{_name}' TLS certificate file must contain a certificate with private key.

What it means

Thrown by BlockPageApp LoadWebServiceTlsCertificate after successfully loading the PKCS #12 bundle if none of the certificates in it contains a private key. A TLS server needs a certificate with its private key, so an empty/private-key-less bundle raises ArgumentException.

Source

Thrown at Apps/BlockPageApp/App.cs:494

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

                X509Certificate2Collection webServerTlsCertificateCollection = X509CertificateLoader.LoadPkcs12CollectionFromFile(webServerTlsCertificateFilePath, webServerTlsCertificatePassword, X509KeyStorageFlags.PersistKeySet);
                X509Certificate2? serverCertificate = null;

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

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

                _sslServerAuthenticationOptions = new SslServerAuthenticationOptions()
                {
                    ServerCertificateContext = SslStreamCertificateContext.Create(serverCertificate, webServerTlsCertificateCollection, false)
                };

                _webServerTlsCertificateLastModifiedOn = fileInfo.LastWriteTimeUtc;

                _dnsServer.WriteLog("Web server '" + _name + "' TLS certificate was loaded: " + webServerTlsCertificateFilePath);
            }

            private void StartTlsCertificateUpdateTimer()
            {
                if (_tlsCertificateUpdateTimer is null)
                {
                    _tlsCertificateUpdateTimer = new Timer(delegate (object? state)
                    {
                        if (!string.IsNullOrEmpty(_webServerTlsCertificateFilePath))

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Re-export the certificate ensuring the private key is included (Windows: 'Yes, export the private key'; OpenSSL: pass -inkey).
  2. Confirm the 'webServerTlsCertificatePassword' matches the bundle so the private key loads.
  3. Validate the PFX contains a key pair before deploying (e.g. 'openssl pkcs12 -info -in file.pfx').

Example fix

# re-export WITH private key
openssl pkcs12 -export -out blockpage.pfx -inkey privkey.pem -in fullchain.pem
# verify a key is present
openssl pkcs12 -info -in blockpage.pfx -nokeys || echo "NO PRIVATE KEY"
Defensive patterns

Strategy: validation

Validate before calling

var coll = X509CertificateLoader.LoadPkcs12CollectionFromFile(path, password, X509KeyStorageFlags.PersistKeySet);
if (!coll.Any(c => c.HasPrivateKey))
    throw new FormatException($"PKCS #12 bundle '{path}' contains no certificate with a private key. Re-export including the private key.");

Type guard

static bool PfxHasPrivateKey(string path, string? password)
{
    var coll = X509CertificateLoader.LoadPkcs12CollectionFromFile(path, password, X509KeyStorageFlags.PersistKeySet);
    return coll.Any(c => c.HasPrivateKey);
}

Prevention

When it happens

Trigger: Loading a .pfx/.p12 that was exported without the private key (e.g. only the public cert chain), so the loop finds no certificate with HasPrivateKey and serverCertificate stays null.

Common situations: Exporting a PFX from a CA/Windows cert store without marking 'export private key'; using a distribution public cert bundle; wrong password silently yielding a key-less result.

Understand the failure class

Related errors


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