I was helping a customer deploy the AWS Landing Zone Accelerator (LZA) to 15 member accounts last week. The pipeline succeeded in the management account, but when it tried to deploy to the member accounts, it failed with cryptic CloudFormation errors. After checking CDK bootstrap stacks and cross-account IAM roles, we discovered three member accounts were missing the bootstrap stack entirely. In this post, I’ll walk through exactly what causes LZA member account deployment failures and how to fix them.
The Problem
Your LZA CodePipeline runs successfully in the management account, but fails when deploying to specific member accounts. You see CloudFormation errors like:
Stack:arn:aws:cloudformation:us-east-1:123456789012:stack/AWSAccelerator-xxxxxxxx does not existUser: arn:aws:iam::123456789012:role/aws-accelerator-role is not authorized to perform: cloudformation:CreateStackNetwork CIDR range 10.0.0.0/16 is already in use
| Error Type | Root Cause |
|---|---|
| Stack does not exist | CDK bootstrap CloudFormation stack missing |
| Not authorized | Cross-account IAM role lacks assume permissions |
| CIDR conflict | Network config overlaps with existing VPCs |
| VPC limit exceeded | Account has reached max VPCs per region |
Why Does This Happen?
The LZA uses AWS CDK, which requires a bootstrap CloudFormation stack in every target account and region before it can deploy. Additionally, the LZA assumes cross-account roles in member accounts to perform deployments. If these prerequisites aren’t met, deployments fail:
- Missing CDK bootstrap stack: The
CDKToolkitCloudFormation stack must exist in the target account/region. Without it, CDK has nowhere to store template artifacts and can’t deploy infrastructure. - Insufficient cross-account permissions: The LZA uses
AWSControlTowerExecutionor a custom cross-account role. If the trust relationship doesn’t allow the management account to assume it, deployments fail. - Network configuration conflicts: If your
network-config.yamlspecifies CIDR ranges that already exist in the target account, CloudFormation will fail to create the VPC. - Service quotas exceeded: AWS accounts have default limits (5 VPCs per region, 5 EIPs per region). If the target account is near or at these limits, deployment fails.
- Target account/region mismatch: If your
accounts-config.yamllists a region that doesn’t match the deployment regions innetwork-config.yaml, the pipeline will try to deploy resources in an account/region pair that doesn’t exist.
The Fix
Step 1: Identify the Failed Account and Region
Check the LZA CodePipeline execution to see which account/region combination failed:
aws codepipeline list-pipeline-executions \
--pipeline-name aws-accelerator-pipeline \
--region us-east-1
Click the failed execution in the console. Look at the stage names—they’re formatted like Deploy-123456789012-us-east-1. This tells you the account and region that failed.
Step 2: Verify CDK Bootstrap in Target Account
Log into the target account and check if the bootstrap stack exists:
# First, assume the cross-account role
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/AWSControlTowerExecution \
--role-session-name lza-check \
--duration-seconds 3600
# Then list CloudFormation stacks
aws cloudformation list-stacks \
--region us-east-1 \
--stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE
Look for a stack named CDKToolkit. If it doesn’t exist, you need to bootstrap the account:
# Still in the assumed role session, run CDK bootstrap
npx cdk bootstrap aws://123456789012/us-east-1 \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
Repeat this for every account/region pair that failed. Check your accounts-config.yaml to see which regions are enabled per account.
Step 3: Verify Cross-Account Trust Relationship
Ensure the cross-account role has the correct trust relationship:
# In the target account, describe the role
aws iam get-role \
--role-name AWSControlTowerExecution
# Get the trust policy
aws iam get-role-policy \
--role-name AWSControlTowerExecution \
--policy-name AssumeRolePolicy
The trust policy should allow the management account to assume the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::MANAGEMENT-ACCOUNT-ID:role/aws-accelerator-role"
},
"Action": "sts:AssumeRole"
}
]
}
If the trust policy is incorrect, update it:
aws iam update-assume-role-policy \
--role-name AWSControlTowerExecution \
--policy-document file://trust-policy.json
Step 4: Check Network Configuration
Review your network-config.yaml to ensure CIDR ranges don’t conflict:
# In target account, list existing VPCs
aws ec2 describe-vpcs \
--region us-east-1 \
--query 'Vpcs[].CidrBlock'
If your network config specifies a CIDR that already exists, edit network-config.yaml and choose a non-overlapping range. Then retry the pipeline.
Step 5: Check Service Quotas
Verify you haven’t hit VPC or EIP limits:
# Check VPC quota
aws service-quotas get-service-quota \
--service-code vpc \
--quota-code L-F678F1CE \
--region us-east-1
# Check EIP quota
aws service-quotas get-service-quota \
--service-code ec2 \
--quota-code L-0287A674 \
--region us-east-1
If you’re near the limit, request an increase:
aws service-quotas request-service-quota-increase \
--service-code vpc \
--quota-code L-F678F1CE \
--desired-value 20 \
--region us-east-1
Step 6: Retry the Pipeline
Once all prerequisites are met:
aws codepipeline start-pipeline-execution \
--pipeline-name aws-accelerator-pipeline \
--region us-east-1
Is This Safe?
Bootstrapping accounts and verifying IAM roles is safe. Requesting service quota increases is also safe—they’re typically approved within minutes. Just avoid changing network CIDR ranges without careful planning.
Key Takeaway
LZA member account deployment failures usually stem from missing CDK bootstrap stacks, cross-account role trust issues, or network configuration conflicts. Always bootstrap every account/region combination, verify cross-account trust relationships, and ensure your network config doesn’t conflict with existing VPCs before retrying.
Have questions or ran into a different LZA issue? Connect with me on LinkedIn or X.