Skip to content

AWS::EarlyValidation::ResourceExistenceCheck blocking all CloudFormation changesets - SES identity confirmed verified but hook appears to use stale cached status

0

Summary

Every CloudFormation changeset creation on my stack has failed for over 24 hours with:

The following hook(s)/validation failed: [AWS::EarlyValidation::ResourceExistenceCheck]. To troubleshoot Early Validation errors, use the DescribeEvents API for detailed failure information.

The underlying resource (an SES v2 domain identity used by a Cognito User Pool's EmailConfiguration) is independently confirmed fully verified via aws sesv2 get-email-identity — checked seconds before a changeset attempt failed. I believe this hook is checking against a stale cached verification snapshot rather than live status, but I have no way to confirm or clear that cache myself.

Environment

  • Region: eu-west-1
  • Deployed via: AWS SAM CLI (sam deploy) from GitHub Actions
  • Relevant resources: AWS::Cognito::UserPool with EmailConfiguration.EmailSendingAccount: DEVELOPER pointed at an AWS::SES::EmailIdentity for domain framewalk.net

Timeline

  • 2026-08-29: Stack deployed successfully, EmailIdentity + UserPool.EmailConfiguration first added and working (confirmed real email delivery from the domain).
  • 2026-08-30 11:27:59 UTC: A subsequent deploy triggered ses:CreateEmailIdentity on the already-existing framewalk.net identity (CloudTrail confirmed), generating a fresh set of DKIM signing keys. At this exact moment, VerifiedForSendingStatus: false, DKIM Status: NOT_STARTED.
  • 2026-08-30 ~13:34 UTC: DKIM re-verified successfully against the new keys (confirmed in SES console, "DKIM configuration: Successful", timestamp matching key regeneration).
  • 2026-08-30 16:31:25 UTC onward: Every single changeset creation attempt since (11 attempts, spanning over 20 hours, across multiple different template contents - including the exact template that deployed successfully before 11:27:59, redeployed byte-for-byte unchanged) fails identically with the EarlyValidation hook error.

What I've ruled out

  1. The specific resource being unhealthy - aws sesv2 get-email-identity --email-identity framewalk.net, run seconds before a failed deploy attempt, returns:

    "VerifiedForSendingStatus": true,
    "DkimAttributes": { "Status": "SUCCESS", ... },
    "MailFromAttributes": { "MailFromDomainStatus": "SUCCESS", ... },
    "VerificationStatus": "SUCCESS",
    "VerificationInfo": { "LastCheckedTimestamp": "2026-08-31T13:33:24Z", "LastSuccessTimestamp": "2026-08-31T13:33:24Z" }

    This directly contradicts the Cognito-reported error ("Email address is not verified") at essentially the same moment.

  2. Recent template changes being the cause - bisected by redeploying the exact commit that worked successfully before the DKIM regeneration event, completely unchanged. Still fails identically.

  3. A no-op/passthrough quirk - forced a property change on the UserPool resource itself (password policy MinimumLength). Still fails identically, ruling out any "nothing to validate" short-circuit theory.

  4. Drift - aws cloudformation detect-stack-drift / describe-stack-resource-drifts shows resources in sync with the template.

Full error detail (via aws cloudformation list-change-sets, repeated across every failed attempt):

{
  "Status": "FAILED",
  "StatusReason": "The following hook(s)/validation failed: [AWS::EarlyValidation::ResourceExistenceCheck]. To troubleshoot Early Validation errors, use the DescribeEvents API for detailed failure information.",
  "ExecutionStatus": "UNAVAILABLE"
}

The original UserPool-level error (from before this became a pre-changeset-creation block) was:

Cognito received the following error from Amazon SES when attempting to send email:
Email address is not verified. The following identities failed the check in
region EU-WEST-1: arn:aws:ses:eu-west-1:blah:identity/framewalk.net
(Service: CognitoIdentityProvider, Status Code: 400, HandlerErrorCode: InvalidRequest)

What I'm asking

  • Is AWS::EarlyValidation::ResourceExistenceCheck known to cache SES identity verification status rather than checking live, and if so, is there a way to force that cache to refresh (aside from waiting an unknown, apparently >24hr duration)?
  • Is there a way to get more detail than the generic StatusReason above? The error message itself points to "the DescribeEvents API" but I haven't found a call that actually surfaces resource-level detail for a failure at the changeset-creation/pre-flight stage (as opposed to mid-execution stack events, which don't exist for this failure since it never gets that far).
  • Is this a known issue with Cognito UserPool + SES EmailIdentity (DEVELOPER sending mode) combinations specifically?

I'm on the Basic support plan, so a technical support case isn't available to me - posting here as the available path. Happy to provide any additional CLI output, change set IDs, or request IDs that would help (several are already captured above from the CloudTrail/CLI investigation).

Sooooo grateful for any pointers as I'm at a dead end on this now, and it's blocking any deployments. Do I need to destroy everything and start from scratch?

2 Answers
0
Accepted Answer

Hello.

I would not destroy the stack yet.
Try running it against one of the failed change sets:

aws cloudformation describe-events \
  --change-set-name "<failed-change-set-arn>" \
  --region eu-west-1

The result can contain fields such as ValidationStatusReason and ValidationPath, which may identify the exact resource/property that AWS::EarlyValidation::ResourceExistenceCheck is rejecting.
https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-events.html

EXPERT

answered 13 days ago

AWS
SUPPORT ENGINEER

reviewed 13 days ago

0

The API you're looking for exists — note it's DescribeEvents, not the older DescribeStackEvents, which is why you found nothing (your failure happens before any stack events exist). aws cloudformation describe-events returns Early Validation failures. For a change-set-creation failure:

aws cloudformation describe-events \
  --change-set-name <failed-change-set-ARN> \
  --filters '{"FailedEvents":true}' \
  --region eu-west-1

On a VALIDATION_ERROR event you get ValidationName, ValidationStatusReason, and crucially ValidationPath — the specific property that failed — plus LogicalResourceId. That's the detail the generic StatusReason is hiding. If describe-events isn't recognized, your CLI is too old; the SAM CLI in a GitHub Actions runner is often well behind, so check aws --version first.

For remediation text there's also:

aws cloudformation list-hook-results --target-type CHANGE_SET --target-id <change-set-ARN>
aws cloudformation get-hook-result --hook-result-id <id-from-above>

get-hook-result returns Annotations with StatusMessage and RemediationMessage.

Before chasing the caching theory: the check is called ResourceExistenceCheck, and existence isn't verification status. Your identity exists and get-email-identity says it's verified — so if the hook read live SES state it'd pass, and if it's truly an existence check then verification isn't what it's looking at. Read ValidationPath before assuming SES is involved at all.

Also worth separating your two errors. The Cognito "not verified" message was a send-time failure during the DKIM regeneration window; the current one is at change-set creation, before execution. Different layers at different times, not one contradiction — and treating them as a single symptom is probably what's anchoring you to the SES explanation.

To isolate it and unblock deploys meanwhile: you bisected template versions but not the resource. Create a change set with EmailSendingAccount set to COGNITO_DEFAULT, or with EmailConfiguration removed. If it creates cleanly, the problem is that property; if it still fails, SES was never the cause. COGNITO_DEFAULT is a stopgap only — low daily cap, Cognito-branded mail.

Don't tear the stack down. Early validation fails before the change set is created, so nothing has been mutated, which matches your clean drift check. Post the ValidationPath output and this should be answerable.

AWS

answered 13 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.