When I redeploy my AWS Cloud Development Kit (AWS CDK) code, I receive an "Already Exists" error.
Short description
By default, AWS CDK protects certain resources that store user data such as Amazon Simple Storage Service (Amazon S3) buckets and Amazon DynamoDB tables. AWS CDK sets the removalPolicy property for these resources to RETAIN.
When you delete an AWS CloudFormation stack, these resources stay in your AWS account even after the stack reaches the DELETE_COMPLETE state.
If you assigned custom names such as bucketName or tableName for these retained resources, then you receive the "Already Exists" error when you try to redeploy the same CDK code. AWS can't use a name that already exists in your account to create a new resource.
Note: The following examples use an Amazon S3 bucket resource associated with the S3 bucket class in AWS CDK.
Example custom named resource:
const s3Bucket = new s3.Bucket(this, 's3-bucket', {
bucketName: 'amzn-s3-demo-bucket',
versioned: false,
encryption: s3.BucketEncryption.S3_MANAGED
});
To resolve this issue, use one of the following options.
Resolution
Use CloudFormation automatic import
To manage an existing resource with your new CloudFormation stack, use the auto import feature to add it to the stack. This is the simplest solution for most scenarios. CloudFormation's auto-import feature automatically detects and imports existing resources during deployment. For more information, see Import AWS resources into a CloudFormation stack automatically.
To turn on automatic import, complete the following steps:
-
Add a property to your CDK code that specifies the exact name of your existing resource. The name in your code must match the existing resource exactly. Make sure that this identifier matches the existing resource name or identifier. The following is an example CDK code for an existing S3 bucket named my-existing-bucket:
new s3.Bucket(this, 'MyBucket', {
bucketName: 'my-existing-bucket', // Must match the existing resource's name exactly
});
In the preceding example, bucketName specifies the physical name for the bucket.
-
From your CDK project directory, deploy your stack with the --import-existing-resources flag. Run the following command in your terminal:
cdk deploy --import-existing-resources
Manually delete the retained resource
If you don't need to keep the existing resource, then you can delete it manually and redeploy your stack.
Note: This permanently deletes the resource and any data that it contains.
To delete the resource and redeploy your stack, complete the following steps:
- Open the AWS Management Console.
- Navigate to the service console for the retained resource.
- Manually delete the resource.
- From your CDK project directory, run the following command in your terminal to redeploy your AWS CDK stack:
cdk deploy
Change the Resource Name
Update your CDK code to use a different custom name that doesn't conflict with the retained resource. This creates a new resource with a new name. The old resource remains in your account.
To update resource name in CDK code, complete the following steps:
- Open the stack file in your code editor where you defined the resource.
- Update the custom name property to a unique value.
Example:
const s3Bucket = new s3.Bucket(this, 's3-bucket', {
bucketName: 'amzn-s3-demo-bucket-v2', // Changed name
versioned: false,
encryption: s3.BucketEncryption.S3_MANAGED
});
In the preceding example, the S3 bucket name is changed to amzn-s3-demo-bucket-v2.
Note: Different resource types use different naming properties. For example, S3 buckets use bucketName, DynamoDB tables use tableName, and Lambda functions use functionName.
- From your CDK project directory, run the following command in your terminal:
cdk deploy
Remove the Custom Name
Remove the custom name property from your code and AWS CDK automatically generates a unique name for you.
To remove the custom name property, complete the following steps:
- Open the stack file in your code editor where you defined the resource, then remove the custom name property.
Example:
const s3Bucket = new s3.Bucket(this, 's3-bucket', {
// bucketName: 'amzn-s3-demo-bucket-v2', property removed
versioned: false,
encryption: s3.BucketEncryption.S3_MANAGED
});
In the preceding example, without the bucketName property, CDK automatically generates a unique name for the resource.
- From your CDK project directory, run the following command in your terminal to redeploy your stack:
cdk deploy
Use the cdk import command to manually import resources
You can use the cdk import command to manually import resources to the stack. This option gives you precise control over the import process but does require manual steps.
Important: During a cdk import operation, you can't create or update other resources.
To manually import resources to your stack, complete the following steps:
-
Verify that the resource you want to import supports the import operation. To verify, see the Import column for the specific resource type in the Resource type support documentation. If the resource type shows Yes in the Import column, you can proceed.
-
Open your CDK stack file in your code editor and temporarily comment out all other resource definitions. Leave only the resource you want to import uncommented. This is important because cdk import can’t handle other resources during the import process.
-
Make sure the resource definition includes a removal policy set to RETAIN. This prevents accidental deletion if the resource is later removed from the stack.
Example for an S3 Bucket:
const s3Bucket = new s3.Bucket(this, 's3-bucket', {
bucketName: 'amzn-s3-demo-bucket',
removalPolicy: RemovalPolicy.RETAIN
});
-
From your CDK project directory, run the following command in your terminal to start the import:
cdk import
-
When prompted, enter the resource identifier for the resource you want to import. The identifier depends on the resource type. For example, for an S3 Bucket, enter the bucket name such as amzn-s3-demo-bucket.
-
After the import completes successfully, go back to your CDK stack file and uncomment the other resource definitions that you commented out in Step 2.
-
From your project directory, run the following command in your terminal to deploy the complete stack with all resources:
cdk deploy