microsoft/aspire · error · ArgumentException

The provided certificate must have a valid public key.

Error message

The provided certificate must have a valid public key.

What it means

During Certificate init validation the annotation also checks that the certificate exposes a public key (value.PublicKey). If the key is null it throws ArgumentException; if reading the key raises CryptographicException that path instead produces the 'provided certificate is invalid' error. This specific throw means the X509 object parsed but carries no usable public key.

Solutions

  1. Regenerate or re-export the certificate from a trusted source and verify openssl x509 -noout -pubkey succeeds.
  2. Verify the PEM/secret content end-to-end (no truncated base64, correct headers) before loading.
  3. Load the certificate in a probe before constructing the annotation and access cert.PublicKey yourself to catch the problem early with a clear message.
  4. If the cert comes from a mounted secret, check the secret mount and file contents in the deployment environment.

Example fix

// before
var cert = new X509Certificate2(Convert.FromBase64String(envCert));
var annotation = new HttpsCertificateAnnotation { Certificate = cert }; // may throw here
// after
var cert = new X509Certificate2(Convert.FromBase64String(envCert));
if (cert.PublicKey is null) throw new InvalidOperationException("Certificate material has no public key; re-export cert.pfx.");
var annotation = new HttpsCertificateAnnotation { Certificate = cert };
Defensive patterns

Strategy: validation

Validate before calling

// before assigning
if (cert is not null)
{
    _ = cert.PublicKey ?? throw new InvalidOperationException("Certificate has no public key; re-export a valid certificate.");
}

Type guard

static bool HasPublicKey(this X509Certificate2? cert) =>
    cert is not null && cert.PublicKey is not null;

Try / catch

try
{
    var annotation = new HttpsCertificateAnnotation { Certificate = cert };
}
catch (ArgumentException ex) when (ex.Message.Contains("public key"))
{
    // regenerate/re-export the certificate
}

Prevention

When it happens

Trigger: Assigning a corrupt or synthetic X509Certificate2 instance (e.g. built from truncated/blank PEM data that still constructs) to HttpsCertificateAnnotation.Certificate.

Common situations: Certificates generated or transformed programmatically (PEM re-wrapping, base64 mangling in config/env substitution); corrupted mount/secret contents in containers.

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.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/84d7b0e49f11585a. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/ApplicationModel/HttpsCertificateAnnotation.cs:42

    {
        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;
        }
    }

    /// <summary>
    /// Gets or sets a value indicating whether the resource should use a platform developer certificate for its key pair.
    /// </summary>
    public bool? UseDeveloperCertificate
    {
        get => _useDeveloperCertificate;
        init

View on GitHub (pinned to 25830f84bd)