AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides comprehensive support for the AWS CDK, covering the full lifecycle of infrastructure-as-code development. It includes best practices for construct patterns, environment bootstrapping, compliance enforcement, drift detection, and safe refactoring. The skill also offers detailed troubleshooting workflows for common CLI, CloudFormation, and deployment errors, ensuring developers can maintain stable and secure AWS environments using TypeScript or Python.
What it does
- Guides the authoring of AWS infrastructure using L1 and L2 CDK constructs.
- Provides procedures for bootstrapping AWS accounts and regions for CDK usage.
- Enforces security and compliance policies using cdk-nag integration.
- Detects and resolves configuration drift between live resources and CDK templates.
- Offers systematic troubleshooting for deployment failures and asset management issues.
- Details safe refactoring patterns to prevent accidental resource replacement.
When to use it
- When initializing new AWS infrastructure projects in TypeScript or Python.
- When planning complex stack architectures or managing cross-stack references.
- When diagnosing deployment errors or stuck CloudFormation stacks.
- When integrating security compliance checks into the CI/CD pipeline.
- When importing existing AWS resources into a CDK-managed stack.
- When refactoring existing infrastructure without causing data loss or resource replacement.
Advantages
- Reduces risk of accidental resource replacement during stack refactoring.
- Ensures infrastructure compliance through automated policy enforcement.
- Provides clear, actionable steps for resolving complex deployment deadlocks.
- Standardizes project structure and dependency management for CDK apps.
- Offers safe, documented patterns for handling stateful resources and S3 buckets.
Usage examples
- “How do I safely remove a cross-stack reference without breaking my deployment?”
- The agent explains the three-deploy process: weakening the reference strength to WEAK before final removal to avoid the deadly embrace deadlock.
- “My stack is stuck in UPDATE_ROLLBACK_FAILED. How do I fix it?”
- The agent provides commands to use cdk rollback or cdk rollback --orphan to recover the stack state.
- “How can I ensure my CDK app follows AWS best practices?”
- The agent instructs on installing and applying cdk-nag rule packs like AwsSolutionsChecks as an Aspect to the application.
- “I need to import an existing S3 bucket into my CDK stack. What is the process?”
- The agent outlines the cdk import workflow and the necessary steps to align the existing resource with the CDK template.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/aws/aws-cdk/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip aws-cdk.zip -d .agents/skills
Documentation by AWS
AWS CDK
Overview
Domain expertise for CDK construct authoring, deployment workflows, compliance, drift, importing resources, safe refactoring, and troubleshooting CDK CLI / CloudFormation errors.
When NOT to use: Raw CloudFormation YAML/JSON. SAM. Terraform/Pulumi. CI/CD beyond CDK Pipelines. Use builtin knowledge or specialized skills for these.
Critical Warnings
Deadly embrace: Removing a cross-stack reference deadlocks deployment (Export ... cannot be deleted as it is in use by ...). Preferred fix: weaken the reference first — CrossStackReferences.of($RESOURCE).produce(ReferenceStrength.BOTH) then WEAK, then remove (three deploys). Legacy fallback: two-deploy this.exportValue() recipe. See troubleshooting-deployment.
Construct ID changes cause replacement: Renaming/moving a construct changes its logical ID → CloudFormation replaces the resource (data loss for stateful resources). Always cdk diff before deploy. See refactor-and-prevent-replacement.
UPDATE_ROLLBACK_FAILED: Stack is stuck. Fix with cdk rollback $STACK or cdk rollback $STACK --orphan <LogicalId>. Express mode stacks are the exception — they cannot be rolled back at all. See troubleshooting-deployment.
Hotswap and express mode are development-only: --hotswap / --hotswap-fallback bypass CloudFormation and create drift on purpose; --express reports success before resources stabilize and disables automatic rollback. You MUST NOT use either in production. A failed --express deployment cannot be rolled back — recover by rolling forward with another --express deploy. See fast-deployments.
Non-empty S3 buckets persist after destroy: You MUST set both removalPolicy: DESTROY and autoDeleteObjects: true. Versioned buckets are worse — delete markers persist even after apparent deletion.
Common Workflows
| Task | Quick Command | Details |
|---|---|---|
| Bootstrap | cdk bootstrap aws://$ACCOUNT/$REGION | bootstrap-and-project-setup |
| New TS project | cdk init app --language typescript — use tsx, eslint-plugin-awscdk | bootstrap-and-project-setup |
| New Python project | cdk init app --language python — pin deps, use virtualenv | bootstrap-and-project-setup |
| Deploy | cdk synth --strict → cdk diff → cdk deploy | Always diff before deploy to production |
| Fast dev iteration | cdk deploy --hotswap-fallback, cdk watch, or cdk deploy --express — dev only, never production | fast-deployments |
| cdk-nag | Aspects.of(app).add(new AwsSolutionsChecks()) | compliance-and-drift |
| Drift | cdk drift $STACK (use --fail in CI) | compliance-and-drift |
| Import resource | cdk import (interactive or --resource-mapping for CI), cdk deploy --import-existing-resources | import-and-migrate |
| Refactor safely | cdk refactor --unstable=refactor — no property changes in same deploy | refactor-and-prevent-replacement |
Fast Deployments — Hotswap vs Express (dev only)
Both trade safety for speed and you MUST NOT use either in production.
Choosing between them: Use --hotswap / --hotswap-fallback for the fastest loop when you work mostly with hotswappable resources and drift does not matter. Use --express when drift is unacceptable, or your resources are not hotswappable.
Recovery workflows (hotswap drift via --revert-drift, rolling a failed --express deploy forward), the hotswappable-resource rules, and IAM/monitoring enforcement of the prod prohibition are all in the full guide: fast-deployments.
Troubleshooting
| Error | Cause → Fix |
|---|---|
| DeployFailed / DeploymentError | CDK error isn't the root cause. cdk deploy $STACK --verbose, then cdk --unstable=diagnose diagnose $STACK (CLI ≥ 2.1120.0); else aws cloudformation describe-events --stack-name $STACK --filters FailedEvents=true — the first _FAILED event is the cause. Details |
| NoCredentials / ExpiredToken / AssumeRoleFailed | aws sts get-caller-identity + cdk doctor. Expired SSO, missing env, missing sts:AssumeRole. Details |
| Asset errors (CannotFindAsset, FailedToBundleAsset, AssetBuildFailed, AssetPublishFailed) | Path wrong, Docker not running, or bootstrap bucket perms. Use path.join(__dirname, ...). Details |
| AppRequired | Add "app": "npx tsx bin/my-app.ts" to cdk.json. Details |
| AnnotationErrors | Fix the underlying issue; suppress with NagSuppressions only as last resort. Details |
| ConcurrentReadLock / ConcurrentWriteLock | rm -rf cdk.out then re-run. Parallel CI: --output ./cdk.out.$BUILD_ID. Details |
| BootstrapVersionValidation | Re-bootstrap. Match --qualifier everywhere. Details |
| DependencyCycle | Extract shared resource into third stack or use SSM for late-binding. Details |
| UnresolvedAccount | Set explicit env: { account, region } on stack. Commit cdk.context.json. Details |
| NoStacksMatched | CDK uses logical ID (2nd constructor arg), not CFN name. cdk list to find IDs. Details |
| Cannot find module (synth time) | Run npx tsc --noEmit, check cdk.json app path matches tsconfig.json outDir, delete stale .js files. Python: activate venv. Details |
| V1 import paths / duplicate aws-cdk-lib | V1 @aws-cdk/* imports, wrong Construct import, duplicate lib copies in monorepos. Details |
| Lambda Cannot find module (runtime) | Wrong handler value, missing AWS SDK v3 migration, Python deps not bundled. Details |
| API Gateway multi-stage conflicts | Set deploy: false on RestApi, create Deployment and Stage explicitly. Details |
Change didn't deploy under --hotswap | Changes to non-hotswappable resources are silently ignored and only logged — the command still reports success. Read the output; use --hotswap-fallback to force a CloudFormation deployment instead. Details |
Failed --express deploy / can't roll back | Express mode cannot use the Rollback Stack API, and a standard deploy MUST NOT be used to recover it. Roll forward: fix the cause, then cdk deploy $STACK --express. Details |
| Unexpected drift on a dev stack | Hotswap and cdk watch create drift by design. Until reverted, the live resources — not CloudFormation's records — are authoritative. Reconcile with cdk deploy $STACK --revert-drift, which uses Drift Aware Changesets to bring live resources in line with the template (updates reality to match desired state; does NOT rewrite CF records to match drifted resources). Details |
Construct Patterns
Prefer L2. Use L1 with Mixins/Facades when L2 lacks a property. Escape hatches: node.defaultChild → addPropertyOverride. See construct-patterns.
Additional Resources
Search AWS documentation for "CDK Developer Guide", "CDK API Reference" and "CDK Pipelines" respectively
Security Considerations
OIDC for CI/CD credentials (no static keys)
--custom-permissions-boundaryon bootstrapgrant*()for inter-resource IAMcdk-nag+--strictin CIStateful resources in own stack with
terminationProtection: trueCommit
cdk.context.json
Files
- ATTRIBUTION.mdAdded by AutoGineer879 B
- LICENSELicence file added by AutoGineer9.9 KiB
- NOTICELicence file added by AutoGineer67 B
- SKILL.md8.7 KiB
- references/bootstrap-and-project-setup.md8.0 KiB
- references/compliance-and-drift.md5.2 KiB
- references/construct-patterns.md10.4 KiB
- references/fast-deployments.md13.4 KiB
- references/import-and-migrate.md6.3 KiB
- references/refactor-and-prevent-replacement.md6.2 KiB
- references/troubleshooting-credentials.md5.8 KiB
- references/troubleshooting-deployment.md12.9 KiB
- references/troubleshooting-synth.md8.8 KiB
- references/v1-to-v2-migration.md3.2 KiB
references/troubleshooting-deployment.md
Troubleshooting: Deployment Failures
Table of Contents
Overview
Deploy Failure Root Cause Analysis
Deadly Embrace (Cross-Stack Reference Deadlock)
UPDATE_ROLLBACK_FAILED Recovery
Non-Empty Bucket Deletion
Overview
This reference covers deployment-time failures — errors that occur after cdk synth succeeds and CloudFormation begins creating or updating resources. The CDK CLI error message is almost never the root cause; you MUST inspect CloudFormation stack events to find the actual failure.
Three error categories exist:
| Category | Meaning |
|---|---|
DeployFailed | CloudFormation resource-level failure |
DeploymentError | Asset publishing or IAM permission failure before CFN executes |
EarlyValidationFailure | Pre-deploy check failed (e.g., bootstrap version mismatch) |
Deploy Failure Root Cause Analysis
The CDK CLI surfaces only a terse summary; the real cause is in the failed deployment, not the CLI output. You MUST work through these steps in order.
Step 1: Re-run with --verbose
cdk deploy $STACK --verbosePrints every AWS API call, the change-set diff, and a fuller stack trace (-vv / -vvv for more).
Step 2: cdk diagnose (preferred, CDK CLI ≥ 2.1120.0)
cdk --unstable=diagnose diagnose $STACKInspects the failed deployment and prints the root cause with pointers back to the CDK source that caused it. It runs after the fact, so it also works for diagnosing CI/CD pipeline failures. Requires the --unstable=diagnose flag.
Step 3: CloudFormation events (fallback)
If cdk diagnose is unavailable (older CLI) or you need the raw stream:
aws cloudformation describe-events --stack-name $STACK --filters FailedEvents=truedescribe-events groups events by operation ID and surfaces validation, provisioning, and hook-invocation errors — it supersedes describe-stack-events. The FIRST event in the output is the real root cause; later failures are rollback cascade.
Step 4: Read the ResourceStatusReason
| Reason | Likely cause → fix |
|---|---|
... already exists | Physical-name collision — remove bucketName/tableName/roleName and let CDK auto-generate. |
resource creation cancelled | Not the root — another resource failed first; find that event. |
... in the WAITING state for approximately ... seconds | Stabilization timeout (RDS, ASG signals, long-running Lambda). |
Export X cannot be deleted as it is in use by Stack Y | Cross-stack deadlock — see Deadly Embrace. |
is not authorized to perform ... | The default CDK bootstrap grants AdministratorAccess to the execution role — this error means you're using a customized bootstrap with a restricted execution role, a permissions boundary, or an SCP. Check which specific action/resource is denied, then add only that permission to your custom execution role or permissions boundary. Do NOT widen to * — grant the minimum action on the minimum resource ARN. |
Step 5: Service logs for Lambda / API Gateway / custom resources
CloudFormation only reports that a resource failed. The actual reason (e.g. a custom-resource Lambda threw) is in CloudWatch Logs:
Lambda:
/aws/lambda/<function-name>CodeBuild-in-pipeline:
/aws/codebuild/<project>CloudFormation custom resources: the backing Lambda's log group.
EarlyValidationFailure specifically
Fails BEFORE the change set is submitted — a construct's validate() returned errors, a synth-time assertion tripped, or an addError annotation fired. The message names the exact property and constraint; fix it before redeploying.
If you have the awslabs
aws-iac-mcp-server, itstroubleshoot_cloudformation_deploymenttool matches the failure event stream against 30+ known patterns and returns CloudTrail deep links — use it to shortcut Steps 2–4.
Deadly Embrace (Cross-Stack Reference Deadlock)
A deadly embrace occurs when Stack A exports a value that Stack B imports, and you then try to remove the export (or the resource behind it). CloudFormation refuses:
Export Stack1:ExportsOutputFnGetAtt-XXXX cannot be deleted as it is in use by Stack2
The deadlock is structural: a safe removal needs B deployed first (so it stops importing), but CDK orders A before B because of the dependency.
Every cross-stack reference has a strength:
Strong (default) — uses
Fn::ImportValue. CloudFormation blocks the producer from removing the export while any consumer still imports it.Weak — uses
Fn::GetStackOutput. No coupling; the producer can be changed or deleted independently.Both — transitional state for migrating strong → weak.
Cross-account references are always weak (strong is unsupported cross-account).
Fix — reference strength (recommended)
CDK supports weakening the reference before removing the resource, with no manual exportValue hacks. You MUST do this as a three-deploy migration.
Weaken all references to a resource — CrossStackReferences.of(resource).produce():
import { CrossStackReferences, ReferenceStrength } from 'aws-cdk-lib';
// Deploy 1 — consumers move to Fn::GetStackOutput; the strong export stays
CrossStackReferences.of(bucket).produce(ReferenceStrength.BOTH);
// Deploy 2 — drop the strong export now that no consumer uses Fn::ImportValue
CrossStackReferences.of(bucket).produce(ReferenceStrength.WEAK);
// Deploy 3 — remove the resource or the reference entirelyWeaken a single reference — Stack.consumeReference():
import { Stack, ReferenceStrength } from 'aws-cdk-lib';
// Deploy 1 — wrap with consumeReference (defaults to BOTH)
new CfnOutput(consumer, 'BucketArn', { value: Stack.consumeReference(bucket.bucketArn) });
// Deploy 2 — switch to WEAK
new CfnOutput(consumer, 'BucketArn', {
value: Stack.consumeReference(bucket.bucketArn, ReferenceStrength.WEAK),
});
// Deploy 3 — remove the resource or reference(Use Stack.consumeListReference() for string-list references.)
Fix — legacy two-deploy (exportValue)
Use this only on CDK versions that lack ReferenceStrength. It MUST be done in exactly two deployments:
Deploy 1 — decouple the consumer, keep the export alive:
In consumer Stack B, remove the cross-stack reference (replace with a hardcoded value, SSM lookup, etc.).
In producer Stack A, add
this.exportValue(resource.attribute)to keep the export alive during the transition.Deploy both.
Deploy 2 — remove the export:
In Stack A, remove the
this.exportValue()call (and the underlying resource if desired).Deploy again.
You MUST NOT attempt to remove the export and the import in a single deployment.
Manual deploy ordering (cdk deploy -e)
If the consumer already stopped using the value and you control ordering yourself:
cdk deploy -e $CONSUMER_STACK # deploy consumer first (drops the import)
cdk deploy -e $PRODUCER_STACK # then producer, removing the export-e / --exclusively deploys only the named stack and skips dependency reconciliation.
Prevention
Default cross-stack references to weak for resources you expect to remove or replace. Set app-wide in
cdk.json:{ "context": { "@aws-cdk/core:defaultCrossStackReferences": "weak" } }Keep stateful, long-lived resources in their own stack, separate from consumers.
Use SSM Parameter Store as indirection (producer writes a parameter, consumer reads it) — no CFN export, no embrace.
UPDATE_ROLLBACK_FAILED Recovery
A stack enters UPDATE_ROLLBACK_FAILED when CloudFormation cannot roll back a failed update. The stack is wedged and MUST be recovered before any further operations.
First: was the failed deployment an express mode deployment?
If the failed operation was run with --express, the rollback-based recovery below does NOT apply. Express mode deployments cannot use the CloudFormation Rollback Stack API, and a standard CloudFormation deployment MUST NOT be used to recover a failed express mode deployment.
Recover by rolling forward instead — make another express mode deployment that resolves the failure, either by reverting the resource to its last successful state in code or by making another change that fixes the cause:
cdk deploy $STACK --expressSecurity note: A failed express deployment may have left resources partially configured — potentially without intended encryption, access controls, or policy attachments. Inspect the stack's resources (aws cloudformation list-stack-resources) before reusing the environment.
Audit note: Check CloudTrail logs for the failed deployment's API calls to determine which resources were created or modified and in what state they were left. This is the most reliable way to reconstruct exactly which create/update/delete operations succeeded or failed, since express mode reports the stack as failed without recording per-resource stabilization.
Running cdk deploy --express or cdk deploy --express --rollback against an already-failed stack applies the changes without first attempting a rollback, unlike cdk deploy without express mode. See fast-deployments.
Root causes
Resource deleted out-of-band (e.g., manually deleted in the console).
Insufficient IAM permissions for the rollback operation.
Service quota exceeded.
Resource operation timed out.
Recovery options
Option 1 — Standard rollback:
cdk rollback $STACKOption 2 — Orphan stuck resources:
If a specific resource cannot be rolled back (e.g., it was deleted out-of-band), skip it:
cdk rollback $STACK --orphan $LOGICAL_IDThe resource is removed from the stack's state without attempting to delete or update it.
Option 3 — Force rollback:
cdk rollback $STACK --forcePost-recovery steps
After the stack returns to a stable state, you MUST:
Run
cdk diff $STACKto understand the current drift.Fix the root cause (restore deleted resources, fix IAM, request quota increase).
Redeploy:
cdk deploy $STACK.
You SHOULD NOT leave a stack in a recovered-but-drifted state.
Non-Empty Bucket Deletion
Setting removalPolicy: cdk.RemovalPolicy.DESTROY alone MUST NOT be expected to delete an S3 bucket that contains objects. CloudFormation cannot empty a bucket during deletion. Versioned buckets are worse — delete markers and non-current object versions persist even after apparent object deletion, so the bucket can appear empty yet still fail to delete.
Fix
You MUST add autoDeleteObjects: true alongside the removal policy:
new s3.Bucket(this, 'MyBucket', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});autoDeleteObjects installs a custom resource Lambda that deletes all object versions and delete markers before CloudFormation attempts to delete the bucket.
You SHOULD only use this pattern in development or test stacks. Production buckets SHOULD retain the default removalPolicy: RETAIN.
Lambda Cannot Find Module at Runtime
These errors occur at Lambda invoke time, not during cdk synth. The function deploys successfully but fails when invoked.
Symptom
Cannot find module 'index'
Cannot find module 'aws-sdk'
Runtime.ImportModuleError: No module named 'requests'Cause
Wrong
handlervalue (e.g.,handler: 'handler'instead ofhandler: 'index.handler')aws-sdkv2 was removed from Node.js 18+ Lambda runtimes — code still imports itPython dependencies not bundled —
Code.fromAsset()zips the directory without runningpip install
Fix
Fix handler to match your file and export:
handler: 'index.handler'Migrate from AWS SDK v2 to v3:
import { S3Client } from '@aws-sdk/client-s3'Remove
externalModules: ['aws-sdk']from bundling options if presentFor Python: use
PythonFunctionfrom@aws-cdk/aws-lambda-python-alphawhich bundles pip dependencies automatically
API Gateway Multi-Stage
This is a construct design issue that manifests at deploy time, not a synth failure.
Symptom
Creating a RestApi produces only one stage. Adding extra Stage objects causes conflicts or duplicate deployments.
Cause
RestApi creates a Deployment and a default Stage automatically. Creating additional Stage objects without disabling the default causes conflicts.
Fix
Set deploy: false on the RestApi, then create Deployment and Stage objects explicitly:
const api = new apigateway.RestApi(this, 'Api', { deploy: false });
// ... define resources and methods ...
const deployment = new apigateway.Deployment(this, 'Deployment', { api });
new apigateway.Stage(this, 'Dev', { deployment, stageName: 'dev' });
new apigateway.Stage(this, 'Prod', { deployment, stageName: 'prod' });Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python, Needs Node.js
Security
What our scanner noticed· Medium risk
- References to credential files
- Instructions that use the network
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- AWS
- Publisher
- AWS (Official)
- Source
- aws/agent-toolkit-for-aws · skills/core-skills/aws-cdk · commit 0a218f8
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- NOTICE (added by AutoGineer from NOTICE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- aws/agent-toolkit-for-aws
AutoGineer is not affiliated with or endorsed by AWS or AWS.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download aws-cdk.zip