CloudFormation Error: 'Embedded stack was not successfully created' — Cause, Fix, and Troubleshooting Guide
Fix 'Embedded stack ... was not successfully created: The following resource(s) failed to create' in CloudFormation by drilling into nested stack events.
- #iac
- #infrastructure-as-code
- #cloudformation
- #troubleshooting
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
When a CloudFormation stack contains AWS::CloudFormation::Stack resources — nested (child) stacks — the parent stack only reports a summary of the child’s outcome. If a resource inside a child stack fails, the parent surfaces a generic wrapper message and rolls back, but the message does not tell you what actually broke. The real cause is an event inside the child stack, which may itself contain more children.
The parent-level error reads like this:
Embedded stack arn:aws:cloudformation:us-east-1:123456789012:stack/parent-NetworkStack-1A2B3C4D/... was not successfully created: The following resource(s) failed to create: [NatGateway, PrivateRouteTable].
This message is a signpost, not a diagnosis. The [NatGateway, PrivateRouteTable] names are logical IDs inside the child template, and the reason they failed to create lives in that child stack’s own event stream. The entire skill here is drilling from the parent event down into the child (and grand-child) events to find the first real error — everything after it is just cascade noise from the rollback.
Symptoms
- Parent stack goes to
CREATE_FAILED/ROLLBACK_IN_PROGRESSwithEmbedded stack ... was not successfully created. - The named child resources are logical IDs you recognize from a nested template, not the parent.
- The child stack shows
CREATE_FAILEDorDELETE_COMPLETE(rolled back and cleaned up) by the time you look. UPDATE_ROLLBACK_IN_PROGRESSon the parent after a change to a nested template.- The console shows the parent as failed but the child events are already gone because rollback deleted the child.
Common Root Causes
1. A resource in the child template genuinely failed
The most common case: an IAM permission gap, a service quota, an invalid AMI, or a bad parameter inside the child. The parent just relays “these resources failed to create.”
# Inside the child stack's events:
CREATE_FAILED NatGateway Resource creation cancelled
CREATE_FAILED NatGateway The maximum number of addresses has been reached. (Service: AmazonEC2; Status Code: 400; Error Code: AddressLimitExceeded)
2. Parameters passed from parent to child are wrong
Nested stacks receive Parameters from the parent. A missing, mistyped, or empty parameter (for example an empty subnet list or a non-existent VPC ID) fails validation inside the child.
CREATE_FAILED PrivateRouteTable Value () for parameter vpcId is invalid. Subnet is in a different VPC.
3. TemplateURL points at a stale or wrong S3 object
AWS::CloudFormation::Stack loads the child template from an S3 URL. If you updated the child .yaml locally but did not re-upload it, the parent deploys the old version. A 403/404 on the URL also fails the embedded stack immediately.
CREATE_FAILED NetworkStack Template format error: ... (or) S3 error: Access Denied
4. Rollback deleted the evidence
By default, when a child fails, CloudFormation rolls back and deletes the child stack (DELETE_COMPLETE). If you look after the fact, the child and its events are gone, leaving only the parent’s generic wrapper.
5. Cross-stack dependency or timing
A child that depends on an export from a sibling child, or a race where a resource is referenced before it is ready, can fail intermittently.
6. Capabilities not passed through
If a child creates IAM resources, the parent create-stack must include --capabilities CAPABILITY_NAMED_IAM. Without it the child fails at validation.
How to Diagnose
Step 1: Get the full parent event stream, newest last
aws cloudformation describe-stack-events \
--stack-name parent-Stack \
--query "reverse(StackEvents[].{Time:Timestamp,Status:ResourceStatus,Type:ResourceType,Reason:ResourceStatusReason,Id:LogicalResourceId})" \
--output table
Find the AWS::CloudFormation::Stack resource that went CREATE_FAILED. Note its PhysicalResourceId — that is the child stack ARN.
Step 2: Preserve the child before rollback deletes it
If you are deploying interactively, disable rollback so the failed child sticks around for inspection:
aws cloudformation create-stack \
--stack-name parent-Stack \
--template-url https://s3.amazonaws.com/example-bucket/parent.yaml \
--disable-rollback
Or on newer stacks:
aws cloudformation create-stack --stack-name parent-Stack \
--on-failure DO_NOTHING --template-url https://s3.amazonaws.com/example-bucket/parent.yaml
Step 3: Drill into the child stack’s own events
Use the child ARN from Step 1 (works even after DELETE_COMPLETE, within the retention window):
aws cloudformation describe-stack-events \
--stack-name arn:aws:cloudformation:us-east-1:123456789012:stack/parent-NetworkStack-1A2B3C4D/abcd-1234 \
--query "reverse(StackEvents[?ResourceStatus=='CREATE_FAILED'].{Id:LogicalResourceId,Reason:ResourceStatusReason})" \
--output table
Step 4: Find the FIRST failure
The earliest CREATE_FAILED (bottom of the reversed list) is the true root cause. Everything above it is Resource creation cancelled cascade noise. If that resource is itself another AWS::CloudFormation::Stack, repeat Step 3 one level deeper.
Fixes
Fix the underlying resource error in the child
Address the actual reason string — request a quota increase, correct the IAM policy, fix the AMI ID, etc. Example, for the EIP limit above:
aws service-quotas request-service-quota-increase \
--service-code ec2 \
--quota-code L-0263D0A3 \
--desired-value 10
Re-upload the child template and reference the new version
If the child template drifted, re-upload and (ideally) use versioned object keys so the parent always points at a fresh artifact:
aws s3 cp child-network.yaml s3://example-bucket/network/v7/child-network.yaml
# Update parent TemplateURL to the v7 path, then update the parent stack.
Validate parameters passed to the child
Confirm the parent is passing real values. Use validate-template and a change-set dry run:
aws cloudformation validate-template --template-url https://s3.amazonaws.com/example-bucket/network/v7/child-network.yaml
aws cloudformation create-change-set --stack-name parent-Stack --change-set-name preview \
--template-url https://s3.amazonaws.com/example-bucket/parent.yaml --change-set-type UPDATE
Pass IAM capabilities through the parent
aws cloudformation deploy \
--stack-name parent-Stack \
--template-file parent.yaml \
--capabilities CAPABILITY_NAMED_IAM
What to Watch Out For
- Always diagnose from the first
CREATE_FAILEDin the deepest child, not the parent wrapper message. - Use
--disable-rollback/--on-failure DO_NOTHINGduring development so failed child stacks are preserved for inspection. - Version your nested-template S3 keys; overwriting the same key hides which template actually deployed.
- Keep nesting shallow (two levels is usually plenty) — deep nesting makes root-cause hunting exponentially harder.
- Ensure
CAPABILITY_NAMED_IAM/CAPABILITY_AUTO_EXPANDpropagate from the parent when children create IAM or macros. - Watch service quotas (EIPs, NAT gateways, VPCs) in the target account — nested networking stacks hit these limits constantly.
Related Guides
- CloudFormation UPDATE_ROLLBACK_FAILED
- CloudFormation Circular Dependency Between Resources
- CloudFormation ROLLBACK_COMPLETE: Stack Cannot Be Updated
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.