Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Infrastructure as Code By James Joyner IV · · 9 min read

CloudFormation Error: 'Embedded stack was not successfully created' — Cause, Fix, and Troubleshooting Guide

Quick answer

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
Free toolkit

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_PROGRESS with Embedded 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_FAILED or DELETE_COMPLETE (rolled back and cleaned up) by the time you look.
  • UPDATE_ROLLBACK_IN_PROGRESS on 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_FAILED in the deepest child, not the parent wrapper message.
  • Use --disable-rollback / --on-failure DO_NOTHING during 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_EXPAND propagate 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.
Free download · 368-page PDF

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.