Back to blog
AWSBest PracticesCloud SecurityNetworking

ACM Certificate Validation Failed: Why It Happens and How to Fix It

Learn why AWS ACM certificate validation fails, the real risks of an unissued cert, and step-by-step DNS, CAA, and Terraform fixes to keep TLS working.

TL;DR

ACM cannot issue your certificate because validation failed, usually a missing or wrong DNS record. Until it validates, the cert never reaches ISSUED status and any load balancer or CloudFront distribution relying on it serves the wrong cert or breaks TLS. Fix it by adding the exact CNAME validation record ACM expects, then re-request if the cert is stuck in a failed state.

You requested a certificate from AWS Certificate Manager, attached it to a planned listener, and then nothing happened. The certificate sits there refusing to flip to ISSUED, and your deployment stalls. The ACM Certificate Validation Failed check flags exactly this situation: a certificate that ACM has tried to validate and could not, which means it can never be issued in its current state.

This is one of those problems that looks trivial until it blocks a production launch at 2am. Let's walk through what the check catches, why a failed validation is more than a minor annoyance, and how to get the cert issued and keep it that way.


What this check detects

The acm_validationfailed check looks at the validation status of your ACM certificates and raises a finding when one is in a FAILED validation state. ACM reports this through the certificate's domain validation status, and a failed validation means the certificate authority could not confirm that you control the domains listed on the certificate.

ACM offers two validation methods:

  • DNS validation — ACM gives you a CNAME record to add to your domain's DNS. It checks for that record on a loop until it appears.
  • Email validation — ACM sends an approval email to the domain's registered contacts and a set of common admin addresses.

When either method does not succeed within the allowed window, or when ACM hits a hard error like an unreachable CAA record or an invalid domain, the certificate's validation status becomes FAILED. A certificate in this state is dead weight. It cannot serve traffic, and you cannot simply nudge it back to life.

Note: DNS-validated certificates can renew automatically forever as long as the validation CNAME stays in place. Email-validated certificates require manual re-approval every renewal cycle, which is one of several reasons DNS validation is the recommended path.


Why it matters

A failed certificate is not a passive issue. It has direct, visible consequences.

Your deployment is blocked

If you provisioned the certificate through Terraform or CloudFormation with the intent of attaching it to an Application Load Balancer, API Gateway, or CloudFront distribution, the dependent resource cannot come up. Terraform's aws_acm_certificate_validation resource will wait, then time out. The whole apply fails and your release sits half-finished.

Users hit TLS errors

If the certificate was meant to replace an expiring one, a failed validation means the old cert keeps ticking toward expiry with no working replacement. When it lapses, browsers throw NET::ERR_CERT_DATE_INVALID and API clients reject the connection outright. From a customer's point of view, your site is down.

Warning: ACM stops attempting validation after 72 hours for DNS validation. If the CNAME is not in place by then, the certificate moves to a permanent failed state and you must request a new one. The clock starts the moment you request the cert, not when you remember to add the record.

It signals a control gap

A failed validation often means nobody owns the DNS for that domain, the record was added to the wrong hosted zone, or a CAA record is silently blocking Amazon from issuing. Each of those is a small misconfiguration that tends to recur across teams. One failed cert today usually means three more next quarter unless you fix the underlying process.


How to fix it

The fix depends on why validation failed. Start by inspecting the certificate to see the exact reason.

Step 1: Find the failure reason

aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:111122223333:certificate/abc-123 \
  --region us-east-1 \
  --query 'Certificate.{Status:Status,DomainValidation:DomainValidationOptions,FailureReason:FailureReason}'

Look at FailureReason and the per-domain ValidationStatus. Common values include:

  • NO_AVAILABLE_CONTACTS — email validation found no valid contacts.
  • DOMAIN_VALIDATION_DENIED — the request was explicitly rejected.
  • CAA_ERROR — a CAA DNS record forbids Amazon from issuing.
  • DOMAIN_NOT_ALLOWED — the domain is on a deny list (rare, e.g. high-risk TLDs).

Step 2: For DNS validation, add the exact CNAME record

Pull the record ACM expects. Note the values are case-sensitive and the name often includes a leading underscore label.

aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:111122223333:certificate/abc-123 \
  --query 'Certificate.DomainValidationOptions[].ResourceRecord'

If your DNS lives in Route 53, you can create the record directly. Save the following to validation.json, swapping in the Name and Value from the previous command:

{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "_a1b2c3.example.com.",
        "Type": "CNAME",
        "TTL": 300,
        "ResourceRecords": [
          { "Value": "_x9y8z7.acm-validations.aws." }
        ]
      }
    }
  ]
}
aws route53 change-resource-record-sets \
  --hosted-zone-id Z123456ABCDEFG \
  --change-batch file://validation.json

Tip: ACM can write the Route 53 record for you in a single call. After requesting the cert, run aws acm describe-certificate to get the ARN, then create the record with the JSON above, or skip the manual step entirely and let Terraform's aws_route53_record + aws_acm_certificate_validation pair handle it. More on that below.

Step 3: Clear a CAA error if that was the cause

If FailureReason was CAA_ERROR, your domain has a CAA record that does not list Amazon. Check it:

dig CAA example.com +short

Add Amazon's issuing CAA value so ACM is permitted to issue:

example.com.  300  IN  CAA  0 issue "amazon.com"

Step 4: Re-request the certificate

A certificate already in FAILED status cannot recover, even after you fix DNS. Request a fresh one once the validation record or CAA fix is in place.

Danger: Do not delete the old, in-use certificate before the new one reaches ISSUED and is attached to every listener. ACM blocks deletion of a cert that is still associated with a load balancer or CloudFront distribution, but if you force-detach first, you will drop TLS for live traffic.

aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names www.example.com \
  --validation-method DNS \
  --region us-east-1

Add the new validation record, wait for ISSUED, then attach it and retire the failed one.


How to prevent it from happening again

Manual cert requests are where validation failures breed. Move the whole lifecycle into infrastructure as code so the validation record is created in the same apply as the certificate.

Terraform that validates itself

resource "aws_acm_certificate" "main" {
  domain_name               = "example.com"
  subject_alternative_names = ["www.example.com"]
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  zone_id = aws_route53_zone.main.zone_id
  name    = each.value.name
  type    = each.value.type
  records = [each.value.record]
  ttl     = 300
}

resource "aws_acm_certificate_validation" "main" {
  certificate_arn         = aws_acm_certificate.main.arn
  validation_record_fqdns = [for r in aws_route53_record.validation : r.fqdn]
}

With this pattern, Terraform requests the cert, writes the exact CNAME ACM asks for into the correct hosted zone, and blocks the apply until validation completes. The class of failure where someone typos a record name or targets the wrong zone simply cannot happen.

Tip: The create_before_destroy lifecycle rule lets you change SANs or rotate certificates without a window of broken TLS. The new cert is issued and validated before the old one is removed.

Gate it in CI/CD

Add a check to your pipeline that scans for ACM certificates in PENDING_VALIDATION or FAILED status after a deploy and fails the build if any are found. A short script catches drift before it reaches anyone's browser:

FAILED=$(aws acm list-certificates \
  --certificate-statuses FAILED \
  --query 'CertificateSummaryList[].CertificateArn' \
  --output text)

if [ -n "$FAILED" ]; then
  echo "Found certificates in FAILED state: $FAILED"
  exit 1
fi

Continuous monitoring

IaC and CI gates catch what you deploy on purpose. They do not catch a cert someone clicked together in the console, or a CAA record a domain admin added last week. Lensix runs acm_validationfailed continuously across your accounts so a failed validation surfaces as a finding regardless of how the certificate was created, and well before its predecessor expires.


Best practices

  • Prefer DNS validation over email. It supports automatic renewal and does not depend on someone reading an inbox. Email validation breaks every renewal cycle if the contact leaves.
  • Keep validation CNAMEs in place permanently. Removing the record after issuance breaks the automatic renewal that ACM performs roughly 60 days before expiry.
  • Audit CAA records before requesting certs for new domains. A restrictive CAA set by a security team is a common silent cause of CAA_ERROR.
  • Request certificates in the right region. CloudFront requires certs in us-east-1. A cert validated in the wrong region is technically issued but useless for the distribution you wanted.
  • Use a single hosted zone of record per domain. Split-horizon DNS and orphaned zones are why validation records land somewhere ACM never checks.
  • Set alerts on certificate expiry, not just validation. A validation that failed silently is only the first half of the problem. The second half is the old cert expiring with no replacement.

Validation failures are almost always a DNS or process problem, not an ACM problem. Move certificate issuance into code, keep the validation records where ACM expects them, and monitor for the failed state continuously. Do that and this check stays green without anyone thinking about it.