AWS CDK Error: 'is not authorized to perform: cloudformation:CreateChangeSet' — Cause, Fix, and Troubleshooting Guide
Fix the CDK deploy error 'is not authorized to perform: cloudformation:CreateChangeSet' by fixing deploy-role trust, IAM policies, and bootstrap permissions.
- #iac
- #infrastructure-as-code
- #cdk
- #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
This error appears during cdk deploy when the identity CDK is using does not have permission to call cloudformation:CreateChangeSet. Modern CDK does not apply templates directly with UpdateStack; it creates a change set, waits for it, then executes it. If the caller (or the bootstrap deploy role it assumes) lacks CreateChangeSet, the deploy fails before any resource is touched.
You will see this during cdk deploy:
❌ MyAppStack failed: User: arn:aws:iam::123456789012:user/deployer is not authorized to perform:
cloudformation:CreateChangeSet on resource:
arn:aws:cloudformation:us-east-1:123456789012:stack/MyAppStack/* because no identity-based policy
allows the cloudformation:CreateChangeSet action
(Service: AmazonCloudFormation; Status Code: 403; Error Code: AccessDenied)
The tricky part with modern CDK bootstrap (hnb659fds qualifier) is that the user running cdk deploy usually only needs permission to sts:AssumeRole the four bootstrap roles. The heavy CloudFormation permissions live on cdk-hnb659fds-deploy-role-*. So this error can mean either “your user policy is missing the action” or “you never assumed the deploy role and CDK fell back to your raw user credentials.”
Symptoms
cdk deployfails immediately withAccessDeniedandcloudformation:CreateChangeSet.- The ARN in the message is a
user/orassumed-role/that is NOT thecdk-hnb659fds-deploy-role. cdk diffworks (read-only) butcdk deployfails.- CI pipelines fail here after switching accounts, roles, or rotating credentials.
cdk deploy MyAppStack
Do you wish to deploy these changes (y/n)? y
MyAppStack: creating CloudFormation changeset...
❌ MyAppStack failed: User: arn:aws:iam::123456789012:user/deployer is not authorized to perform:
cloudformation:CreateChangeSet
Common Root Causes
1. CDK is using raw user credentials instead of the bootstrap deploy role
If credential assumption fails silently, CDK proceeds with your caller identity, which typically lacks broad CloudFormation rights. Notice the ARN is a plain user, not a cdk-hnb659fds-deploy-role.
current credentials could not be used to assume
'arn:aws:iam::123456789012:role/cdk-hnb659fds-deploy-role-123456789012-us-east-1',
but are for the right account. Proceeding anyway.
2. The IAM user/role policy simply omits the action
A least-privilege policy that lists CreateStack/UpdateStack but forgets CreateChangeSet, ExecuteChangeSet, and DescribeChangeSet.
Missing: cloudformation:CreateChangeSet, ExecuteChangeSet, DeleteChangeSet, DescribeChangeSet
3. A permissions boundary or SCP denies the action
An explicit Deny in an Organizations SCP or a permissions boundary overrides any Allow, so even an admin-looking policy fails.
aws organizations describe-policy --policy-id p-examplepolicy
4. Resource-scoped policy that does not match the stack ARN
A policy scoped to stack/prod-* will deny a stack named MyAppStack. The Resource ARN pattern must cover the stack, including the /* suffix change sets use.
5. Wrong account/role in the active profile
The credentials in scope belong to a sandbox account while the stack targets production, so the identity genuinely has no rights there.
aws sts get-caller-identity
How to Diagnose
Confirm who CDK actually is
aws sts get-caller-identity
Compare the returned ARN to the ARN in the error. If they match your human/CI user rather than cdk-hnb659fds-deploy-role, role assumption is the problem, not the policy.
Check whether the deploy role exists and is assumable
aws iam get-role --role-name cdk-hnb659fds-deploy-role-123456789012-us-east-1
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/cdk-hnb659fds-deploy-role-123456789012-us-east-1 \
--role-session-name diag
Simulate the exact action
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/deployer \
--action-names cloudformation:CreateChangeSet \
--resource-arns "arn:aws:cloudformation:us-east-1:123456789012:stack/MyAppStack/*"
Look for EvalDecision: allowed vs explicitDeny (SCP/boundary) vs implicitDeny (missing grant).
Run deploy with verbose credential logging
cdk deploy MyAppStack --verbose
Search the output for could not be used to assume — that line is the smoking gun for silent fallback.
Fixes
Fix A (preferred): let CDK assume the bootstrap deploy role
Grant your CI/user identity permission to assume the CDK roles, then keep CloudFormation permissions on the deploy role where bootstrap already put them.
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::123456789012:role/cdk-*"
}
Re-bootstrap if the roles are missing or old:
cdk bootstrap aws://123456789012/us-east-1
Fix B: grant the CloudFormation actions directly
If you deliberately deploy with raw credentials (--no-role style setups), add the full change-set action set.
{
"Effect": "Allow",
"Action": [
"cloudformation:CreateChangeSet",
"cloudformation:ExecuteChangeSet",
"cloudformation:DescribeChangeSet",
"cloudformation:DeleteChangeSet",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:GetTemplate"
],
"Resource": "arn:aws:cloudformation:us-east-1:123456789012:stack/MyAppStack/*"
}
Fix C: widen the resource scope
Change set operations reference stack/<name>/*. Ensure your policy Resource matches the real stack name, not a stale prefix.
Fix D: clear an SCP / boundary deny
Explicit denies win. Update the SCP or permissions boundary to stop denying cloudformation:CreateChangeSet, or deploy from an account/role the org policy permits.
What to Watch Out For
- Do not “fix” this by attaching
AdministratorAccessto a CI user. Prefer the assume-role model so the powerful policy stays on the bootstrap role. CreateChangeSetalone is not enough — you also needExecuteChangeSetor the deploy stalls right after creating the change set.- After
cdk bootstrapupgrades, the deploy role’s inline policy can change; re-bootstrap all target regions, not just one. - The
Proceeding anywaywarning is not benign; treat it as a hard failure signal in CI by checking exit codes. - Custom bootstrap qualifiers change the role names — a hard-coded
hnb659fdsin your IAM policy will not match a custom-qualified bootstrap.
Related Guides
- AWS CDK: Has the environment been bootstrapped?
- AWS CDK Cross-Environment Reference Error
- Managing Secrets in Infrastructure as Code
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.