Always getting dirty state after a resource is first created

I keep finding that my state is dirty after a resource is first created - ie, the second terraform apply results in a “Objects have changed outside of Terraform” warning. I can’t figure out if that’s just expected behaviour and everyone runs terraform apply -refresh-only all the time, or I’m managing to trigger a bug that it seems like everyone ought to be running into.

Here’s a trivial example:

terraform {
  required_version = ">= 0.14.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.74"
    }
  }
}

provider "aws" {
}

resource "aws_iam_user" "terraformtest" {
  name = "terraformuser1"
}

resource "aws_iam_user" "terraformtest2" {
  name = "terraformuser2"
  tags = {
    foo = "bar"
  }
}

In the first run, it creates two users (one with tags, one without) :

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_iam_user.terraformtest will be created
  + resource "aws_iam_user" "terraformtest" {
      + arn           = (known after apply)
      + force_destroy = false
      + id            = (known after apply)
      + name          = "terraformuser1"
      + path          = "/"
      + tags_all      = (known after apply)
      + unique_id     = (known after apply)
    }

  # aws_iam_user.terraformtest2 will be created
  + resource "aws_iam_user" "terraformtest2" {
      + arn           = (known after apply)
      + force_destroy = false
      + id            = (known after apply)
      + name          = "terraformuser2"
      + path          = "/"
      + tags          = {
          + "foo" = "bar"
        }
      + tags_all      = {
          + "foo" = "bar"
        }
      + unique_id     = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_iam_user.terraformtest: Creating...
aws_iam_user.terraformtest2: Creating...
aws_iam_user.terraformtest: Creation complete after 1s [id=terraformuser1]
aws_iam_user.terraformtest2: Creation complete after 1s [id=terraformuser2]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Then if I immediately run terraform apply again, it claims that terraformuser1 has gained a new (empty) tags attribute.

aws_iam_user.terraformtest: Refreshing state... [id=terraformuser1]
aws_iam_user.terraformtest2: Refreshing state... [id=terraformuser2]

Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

  # aws_iam_user.terraformtest has changed
  ~ resource "aws_iam_user" "terraformtest" {
        id            = "terraformuser1"
        name          = "terraformuser1"
      + tags          = {}
        # (5 unchanged attributes hidden)
    }


Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using ignore_changes, the following plan may include actions to undo or respond to these changes.

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

No changes. Your infrastructure matches the configuration.

Your configuration already matches the changes detected above. If you'd like to update the Terraform state to match, create and apply a refresh-only plan:
  terraform apply -refresh-only

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Refreshing shows that the tags attribute in the state file changed from null to {}, and then subsequent runs show a clean state.


Is something weird going on or is this just expected behaviour?

Hi @jdelStrother,

This is expected right now, only because it is caused by known issues with the legacy SDK and some provider resources. Since the plan shows that none of the external changes are affecting your configuration, the external changes are just informational in nature and will be updated on the next apply.

@jbardin thanks for confirming.
You mentioned a legacy sdk - you mean the underling aws-sdk library used by the AWS provider? Or am I using something out-of-date that’s since been replaced?

There is a new Terraform plugin SDK under development, but it’s going to take a while for all providers, especially large ones like AWS, to be able to update all resources to use it. In the meantime we have to deal with a number of quirks being caused by the old SDK, some of which are these minor normalization problems you are seeing. The data should converge on a stable state after another apply. We are also looking into finding ways to quiet some of the changes while still providing feedback when unexpected external changes could affect the configuration.

1 Like