'Terraform AWS Provider Error: Value for unconfigurable attribute. Can't configure a value for "acl": its value will be decided automatically

Just today, whenever I run terraform apply, I see an error something like this: Can't configure a value for "lifecycle_rule": its value will be decided automatically based on the result of applying this configuration.

It was working yesterday.

Following is the command I run: terraform init && terraform apply

Following is the list of initialized provider plugins:

- Finding latest version of hashicorp/archive...
- Finding latest version of hashicorp/aws...
- Finding latest version of hashicorp/null...
- Installing hashicorp/null v3.1.0...
- Installed hashicorp/null v3.1.0 (signed by HashiCorp)
- Installing hashicorp/archive v2.2.0...
- Installed hashicorp/archive v2.2.0 (signed by HashiCorp)
- Installing hashicorp/aws v4.0.0...
- Installed hashicorp/aws v4.0.0 (signed by HashiCorp)

Following are the errors:

Acquiring state lock. This may take a few moments...
Releasing state lock. This may take a few moments...
╷
│ Error: Value for unconfigurable attribute
│ 
│   with module.ssm-parameter-store-backup.aws_s3_bucket.this,
│   on .terraform/modules/ssm-parameter-store-backup/s3_backup.tf line 1, in resource "aws_s3_bucket" "this":
│    1: resource "aws_s3_bucket" "this" {
│ 
│ Can't configure a value for "lifecycle_rule": its value will be decided
│ automatically based on the result of applying this configuration.
╵
╷
│ Error: Value for unconfigurable attribute
│ 
│   with module.ssm-parameter-store-backup.aws_s3_bucket.this,
│   on .terraform/modules/ssm-parameter-store-backup/s3_backup.tf line 1, in resource "aws_s3_bucket" "this":
│    1: resource "aws_s3_bucket" "this" {
│ 
│ Can't configure a value for "server_side_encryption_configuration": its
│ value will be decided automatically based on the result of applying this
│ configuration.
╵
╷
│ Error: Value for unconfigurable attribute
│ 
│   with module.ssm-parameter-store-backup.aws_s3_bucket.this,
│   on .terraform/modules/ssm-parameter-store-backup/s3_backup.tf line 3, in resource "aws_s3_bucket" "this":
│    3:   acl    = "private"
│ 
│ Can't configure a value for "acl": its value will be decided automatically
│ based on the result of applying this configuration.
╵
ERRO[0012] 1 error occurred:
        * exit status 1

My code is as follows:

resource "aws_s3_bucket" "this" {
  bucket = "${var.project}-${var.environment}-ssm-parameter-store-backups-bucket"
  acl    = "private"

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = data.aws_kms_key.s3.arn
        sse_algorithm     = "aws:kms"
      }
    }
  }

  lifecycle_rule {
    id      = "backups"
    enabled = true

    prefix = "backups/"

    transition {
      days          = 90
      storage_class = "GLACIER_IR"
    }

    transition {
      days          = 180
      storage_class = "DEEP_ARCHIVE"
    }

    expiration {
      days = 365
    }
  }

  tags = {
    Name        = "${var.project}-${var.environment}-ssm-parameter-store-backups-bucket"
    Environment = var.environment
  }
}


Solution 1:[1]

Terraform AWS Provider is upgraded to version 4.0.0 which is published on 10 February 2022.

Major changes in the release include:

  • Version 4.0.0 of the AWS Provider introduces significant changes to the aws_s3_bucket resource.
  • Version 4.0.0 of the AWS Provider will be the last major version to support EC2-Classic resources as AWS plans to fully retire EC2-Classic Networking. See the AWS News Blog for additional details.
  • Version 4.0.0 and 4.x.x versions of the AWS Provider will be the last versions compatible with Terraform 0.12-0.15.

The reason for this change by Terraform is as follows: To help distribute the management of S3 bucket settings via independent resources, various arguments and attributes in the aws_s3_bucket resource have become read-only. Configurations dependent on these arguments should be updated to use the corresponding aws_s3_bucket_* resource. Once updated, new aws_s3_bucket_* resources should be imported into Terraform state.

So, I updated my code accordingly by following the guide here: Terraform AWS Provider Version 4 Upgrade Guide | S3 Bucket Refactor

The new working code looks like this:

resource "aws_s3_bucket" "this" {
  bucket = "${var.project}-${var.environment}-ssm-parameter-store-backups-bucket"

  tags = {
    Name        = "${var.project}-${var.environment}-ssm-parameter-store-backups-bucket"
    Environment = var.environment
  }
}

resource "aws_s3_bucket_acl" "this" {
  bucket = aws_s3_bucket.this.id
  acl    = "private"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
  bucket = aws_s3_bucket.this.id

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = data.aws_kms_key.s3.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "this" {
  bucket = aws_s3_bucket.this.id

  rule {
    id     = "backups"
    status = "Enabled"

    filter {
      prefix = "backups/"
    }

    transition {
      days          = 90
      storage_class = "GLACIER_IR"
    }

    transition {
      days          = 180
      storage_class = "DEEP_ARCHIVE"
    }

    expiration {
      days = 365
    }
  }
}

If you don't want to upgrade your Terraform AWS Provider version to 4.0.0, you can use the existing or older version by specifying it explicitly in the code as below:

terraform {
  required_version = "~> 1.0.11"
  required_providers {
    aws  = "~> 3.73.0"
  }
}

Solution 2:[2]

It's broken because Terraform AWS Provider was updated to version 4.0.0.

If you can't upgrade your version, maybe you could lock your AWS provider version like this:

terraform {
  required_version = "~> 0.12.31"

  required_providers {
    aws  = "~> 3.74.1"
  }
}

Solution 3:[3]

For Terragrunt/Terraform users:

As others have mentioned, AWS Provider upgraded to 4.0. Breaking changes are delineated here (under the git 4.0 tag): GitHub | terraform-provider-aws | v4.0.0

Note the breaking changes to s3. I found 39 references of aws_s3_bucket on the page. The reality is some of us don't have time to address all the breaking changes for our current projects. I have found version 3.74.1 to be quite effective.

To restrict all your Terraform projects which are configured with Terragrunt, inside the root terragrunt.hcl file of your terragrunt repo, you can specify the following:

generate "versions" {
    path      = "versions_override.tf"
    if_exists = "overwrite_terragrunt"
    contents  = <<EOF
    terraform {
        required_providers {
        aws = {
            version = "= 3.74.1"
            source = "hashicorp/aws"
        }
        }
    }
EOF
}

In effect, Terragrunt will generate a versions_override.tf terraform config file which will define the explicit version of 3.74.1.

Solution 4:[4]

I am following the tutorial on terraform docs to create a service on AWS Lambda. https://learn.hashicorp.com/tutorials/terraform/lambda-api-gateway

This configuration

resource "aws_s3_bucket" "lambda_bucket" {
  bucket = random_pet.lambda_bucket_name.id
  acl = "private"
  force_destroy = true
}

will incur the following error.

Error: Value for unconfigurable attribute
  with aws_s3_bucket.lambda_bucket,
  on main.tf line 32, in resource "aws_s3_bucket" "lambda_bucket":
  32:   acl           = "private"
Can't configure a value for "acl": its value will be decided automatically
based on the result of applying this configuration.

Since acl is now read only, update your configuration to use the aws_s3_bucket_acl resource and remove the acl argument in the aws_s3_bucket resource:

resource "aws_s3_bucket" "lambda_bucket" {
  bucket = random_pet.lambda_bucket_name.id

  force_destroy = true
}

resource "aws_s3_bucket_acl" "lamdbda_bucket" {
  bucket = aws_s3_bucket.lambda_bucket.id
  acl = "private"
}

Solution 5:[5]

Quick solution: Keep your project on version 3 until you are ready to move to version 4 following the upgrade guide provided by Terraform here: Terraform AWS Provider Version 4 Upgrade Guide.

In order to do it, freeze your provider as shown below:

terraform {
   required_providers {

    aws = {
         source = "hashicorp/aws"
         version =  "~> 3.74.2"
    }

    consul = {
      source = "hashicorp/consul"
    }
  }

  required_version = ">= 0.13"
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Abdullah Khawer
Solution 3 Abdullah Khawer
Solution 4 Henry
Solution 5 Abdullah Khawer