microsoft/aspire · error · ArgumentException
The provided certificate must have a private key.
Error message
The provided certificate must have a private key.
What it means
HttpsCertificateAnnotation.Certificate requires a certificate with an associated private key, because the annotation is used to configure HTTPS endpoints that must terminate TLS. Assigning an X509Certificate2 whose HasPrivateKey is false throws ArgumentException.
Solutions
- Load a combined PFX containing the private key: new X509Certificate2("cert.pfx", password).
- Combine cert and key PEMs before use: X509Certificate2.CreateFromPemFile(certPem, keyPem), optionally export to PFX for Windows compatibility.
- Re-export the certificate from the CA/store including the private key (pkcs12 format).
- Pre-validate with cert.HasPrivateKey before constructing the annotation and fail with a clear config error.
Example fix
// before
var cert = X509Certificate2.CreateFromPemFile("cert.pem", null); // no key -> throws later
var annotation = new HttpsCertificateAnnotation { Certificate = cert };
// after
var cert = X509Certificate2.CreateFromPemFile("cert.pem", "key.pem");
var annotation = new HttpsCertificateAnnotation { Certificate = cert }; Defensive patterns
Strategy: validation
Validate before calling
// before assigning
if (cert is not null && !cert.HasPrivateKey)
throw new InvalidOperationException("Certificate must include a private key (use PFX or cert+key PEMs)."); Type guard
static bool HasPrivateKey(this X509Certificate2? cert) => cert is not null && cert.HasPrivateKey;
Try / catch
try
{
var annotation = new HttpsCertificateAnnotation { Certificate = cert };
}
catch (ArgumentException ex) when (ex.Message.Contains("private key"))
{
// reload the cert with its key (PFX or CreateFromPemFile(certPem, keyPem))
} Prevention
- Always load PFX (PKCS#12) files that contain the private key.
- Use X509Certificate2.CreateFromPemFile(certPem, keyPem) with both files.
- Check cert.HasPrivateKey immediately after loading.
- Verify secret mounts actually contain the key file, not just the certificate.
When it happens
Trigger: Loading only the public portion of a certificate (e.g. X509Certificate2.CreateFromPemFile with a cert-only PEM, or reading a .cer/.crt file) and assigning it to the Certificate property.
Common situations: Certificate exported without the private key; PFX imported with Exportable/load flags that drop the key; separate cert/key PEM files where only the cert file was passed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- The provided certificate is invalid.
- The provided certificate must have a valid public key.
- Cannot set both UseDeveloperCertificate and Certificate…
- AllocatedEndpoint must use the same network as the…
- Anonymous volumes cannot be read-only.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/bacf99a1ad6f8fb8.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/ApplicationModel/HttpsCertificateAnnotation.cs:35
private bool? _useDeveloperCertificate;
/// <summary>
/// Sets an <see cref="X509Certificate2"/> instance associated with this annotation.
/// If a certificate is provided, it must have a private key; otherwise, an <see cref="ArgumentException"/> is thrown when setting the value.
/// </summary>
public X509Certificate2? Certificate
{
get => _certificate;
init
{
if (value != null && _useDeveloperCertificate == true)
{
throw new ArgumentException("Cannot set both UseDeveloperCertificate and Certificate properties.", nameof(value));
}
if (value?.HasPrivateKey == false)
{
throw new ArgumentException("The provided certificate must have a private key.", nameof(value));
}
try
{
if (value != null && value.PublicKey == null)
{
throw new ArgumentException("The provided certificate must have a valid public key.", nameof(value));
}
}
catch (CryptographicException ex)
{
throw new ArgumentException("The provided certificate is invalid.", nameof(value), ex);
}
_certificate = value;
}
}
View on GitHub (pinned to 25830f84bd)