Skip to content

How do I resolve the "Already Exists" error that I receive when I redeploy my AWS CDK code after I delete the stack from the deployment?

4 minute read
1

When I redeploy my AWS Cloud Development Kit (AWS CDK) code, I receive an "Already Exists" error.

Resolution

Most resources in the AWS CDK Construct Library set the removalPolicy property to the RETAIN state by default. If you don't set the removalPolicy property to RETAIN on your resources, then the resources are orphaned. Orphaned resources remain in your AWS account after you delete the stack and then transition to the DELETE_COMPLETE state.

When you update the stack, AWS CDK removes the resource. If you specified a custom name for the resources, then you might receive an "Already Exists" error when you redeploy the same code.

Note: The following steps use an example Amazon Simple Storage Service (Amazon S3) bucket resource that's 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
 });

Import the retained resource to your new stack

Complete the following steps:

  1. Confirm that your environment meets the requirements to use the cdk import AWS CDK Command Line Interface (CLI) command.
    Note: You can't import a resource into your stack when you update or create other resources in the stack. You can import only one or more resources in a single import operation.

  2. Temporarily remove all other resources from your code except for the resource that you want to retain. The defined properties of the resource that you import must match the properties of the resource that you deployed. For example, import the retained S3 bucket resource s3-bucket.
    Note: To import a resource, you must set a Removal Policy for the resource.
    Example policy:

    const s3Bucket = new s3.Bucket(this, 's3-bucket', {
     bucketName: 'amzn-s3-demo-bucket',
     removalPolicy: RemovalPolicy.RETAIN
     });
    
    //const cfnFunction = new lambda.CfnFunction(this, 'MyCfnFunction', {
    //  code: {
    //  ...
    //    s3Bucket: s3Bucket.bucketArn
    //  },
    //  role: 'role',

    Note: Replace s3-bucket with your S3 bucket name.

  3. Run the following cdk import command to initiate the resource import:

    cdk import
  4. Enter the resource ID when CDK prompts you for it. In this example, enter the name for the S3 bucket.

  5. Re-introduce the resources from your code, and then run the following deploy command:

    cdk deploy

Manually delete the retained resource

Complete the following steps:

  1. Sign in to the AWS Management Console.
  2. Select the service of the resources that you don't want to retain.
  3. Manually delete the resources. For example, to remove the s3.bucket resource, delete the Amazon S3 bucket.
  4. To redeploy the AWS CDK, run the following deploy command:
    cdk deploy

Change the name of the retained resource

Complete the following steps:

  1. Open the AWS CDK code for the resource.
  2. Update the name of the resource to a unique value that doesn't conflict with the name of the retained resource:
    const s3Bucket = new s3.Bucket(this, 's3-bucket', {
     bucketName: 'amzn-s3-demo-bucket',
     versioned: false,
     encryption: s3.BucketEncryption.S3_MANAGED
     });
    Note: The preceding example uses the bucketName parameter to change the name of the s3.Bucket resource. Replace amzn-s3-demo-bucket with your S3 bucket name.

Delete the resource name

To delete the resource name so that AWS CDK can generate a unique name, complete the following steps:

  1. To remove the resource name from AWS CDK, run the following code:
    const s3Bucket = new s3.Bucket(this, 's3-bucket', {
     versioned: false,
     encryption: s3.BucketEncryption.S3_MANAGED
     });
    Note: The preceding example code removes the bucketName property to allow AWS CDK to generate a new name.
  2. To redeploy AWS CDK, run the following deploy command:
    cdk deploy

Set the removalPolicy property to DESTROY

Complete the following steps:

  1. Open the AWS CDK code for the resources.

  2. Set the removalPolicy property to DESTROY:

    const s3Bucket = new s3.Bucket(this, 's3-bucket', {
     bucketName: 'amzn-s3-demo-bucket',
     removalPolicy: RemovalPolicy.DESTROY
     });
  3. To access the AWS CloudFormation template, run the following cdk synth command:

    cdk synth
  4. Verify that the DeletionPolicy and UpdateReplacePolicy is set to Delete.

11 Comments

This article does not explain the usual action following retaining, which is the intent to re-use the retained resource in the next stack creation. Regardless of using a custom or auto-generated name, how does one import them? The ".from" static functions on the CDK resources for imports are only pointers to the account resources and cannot be resumed with ongoing modifications to the stack resources.

replied 3 years ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

AWS
EXPERT
replied 3 years ago

Unfortunately, this post is very disappointing. Is there a way AWS CDK can be smart to automatically import these retained stateful resources back into the stack? That was the resolution I was hoping to see. Correct me if I'm wrong, but if we'd like to keep the date stored in these resources, we'd have to craft a workaround? Perhaps, rename retained resource and write some script / lambda function to import items?

replied 2 years ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

AWS
EXPERT
replied 2 years ago

What if I want to reuse the resource? That's the main purpose of retaining it in my case also.

replied 2 years ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

AWS
MODERATOR
replied 2 years ago

CDK should automatically import resources that already exist, otherwise it's largely useless for IaC for anything that isn't stateless.

replied 2 years ago

Echoing the replies you have already received on this article. The usual desired behavior is to re-import these already existing resources. You should either explain how to do that manually or implement the behavior for cdk to do this.

replied 2 years ago

I agree with the comments above, we have been facing as well this error with "Resource of type 'AWS::IAM::Role' with identifier 'our-role-name-here' already exists.", although IAM Role have a default removalPolicy property to DESTROY.

replied a year ago

I agree, I expected to see a way to deploy changes retaining the bucket containing the data. Should we handle "manually" the import of the arn?

    def __get_or_create_s3_bucket(self) -> Bucket:
        """
        Retrieves the S3 bucket.  If it exists, it is imported.  If it
        does not exist, a new bucket is created.

        :return: The S3 Bucket
        """
        bucket_arn = Fn.sub("arn:aws:s3:::${bucketName}", {"bucketName": self.bucket_name})
        try:
            # Attempt to import the bucket.
            bucket = Bucket.from_bucket_arn(self.stack, self.bucket_id, bucket_arn)
            print(f"Imported existing bucket: {self.bucket_name}")
            return bucket
replied a year ago

We are getting this error with an AWS Batch job definition in one of our Stacks, however it is not possible to delete Batch job definitions, only deregister them to have them auto-deleted 180 days later. We don't have the option to use a new name, but also can't wait 180 days to have it deleted before redeploying our Stack.

replied a year ago