Skip to content

Show referenced resource addresses for unknown values in plan output #39298

Open

Description

@ritz-p

Terraform Version

### Terraform Version

Terraform v1.16.4

Use Cases

When reviewing a terraform plan, I want to know which Terraform resource an unknown argument refers to before approving the apply.

For example, a security group can be configured with vpc_id = aws_vpc.example.id. When the VPC is being created in the same plan, the security group's vpc_id is displayed as (known after apply). The AWS VPC ID cannot be known yet, but the Terraform reference aws_vpc.example.id is already known from the configuration.

Example configuration

  • main.tf
provider "aws" {
  region                      = "ap-northeast-1"
  access_key                  = "test"
  secret_key                  = "test"
  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true
  endpoints {
    ec2 = "http://kumo:4566"
  }
}
resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "plan-reference-example"
  }
}
resource "aws_security_group" "example" {
  name        = "plan-reference-example"
  description = "Demonstrates an unknown value from a resource reference"
  vpc_id      = aws_vpc.example.id

  tags = {
    Name = "plan-reference-example"
  }
}
  • versions.tf
terraform {
  required_version = "= 1.16.4"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 6.66.0"
    }
  }
}

terraform plan output

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_security_group.example will be created
  + resource "aws_security_group" "example" {
      + arn                    = (known after apply)
      + description            = "Demonstrates an unknown value from a resource reference"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = (known after apply)
      + name                   = "plan-reference-example"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + region                 = "ap-northeast-1"
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Name" = "plan-reference-example"
        }
      + tags_all               = {
          + "Name" = "plan-reference-example"
        }
      + vpc_id                 = (known after apply)
    }

  # aws_vpc.example will be created
  + resource "aws_vpc" "example" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + region                               = "ap-northeast-1"
      + tags                                 = {
          + "Name" = "plan-reference-example"
        }
      + tags_all                             = {
          + "Name" = "plan-reference-example"
        }
    }

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

This VPC example is intentionally simple. In a large plan with many resources, however, seeing only (known after apply) makes it difficult to tell which resource an argument refers to. I would like the plan itself to show that reference so it can be reviewed without tracing it through the configuration.

Attempted Solutions

I ran terraform plan with the configuration shown above. The security group's vpc_id appeared as (known after apply), without indicating that its value comes from aws_vpc.example.id.

I can find the reference by inspecting the Terraform configuration, but I could not find an existing option to display it in the human-readable plan output. I have not tried another workaround.

Proposal

For arguments whose value is unknown because they reference another Terraform resource, show the source reference in plan output.

Current output:

+ vpc_id = (known after apply)

Proposed output (example):

+ vpc_id = (known after apply; from aws_vpc.example.id)

References

Activity

  1. jbardin commented on Sep 28, 2026

    @jbardin
    Member

    Hi @ritz-p,

    This is similar to something that has been thought about many times before, knowing precisely where a value originates would be useful for many things in terraform. Unfortunately, the language we have doesn't allow for such precision.

    Indirection for example is the first obvious case, what do you display for this?

    vpc_id = var.vpc_id
    

    Maybe just displaying var.vpc_id is adequate (though that has complications too ...)
    We have some limited ways to trace values linearly, but then what if your expression was conditional instead?

    vpc_id = var.unknown_at_plan ? aws_vpc.example.id : var.external_vpc
    

    These complications naturally compound as values are coalesced and redistributed through expanded resources and modules. Throw in other expression types, like for-expressions, and then functions calls, and you can see that there are many ways to obfuscate where a value might originate from static analysis.

    With some of the well-trodden background out of the way -- if we're only looking for an incremental enhancement of plan output, then maybe it doesn't need to be exact or present at all times, it just needs to not be wrong?

    In that case, in theory it would be possible to display expressions only when they are direct references to an unknown value being assigned to a block attribute -- the problem there is that we don't even have the expressions! The plan renderer is dealing with the planned values and resource schemas, but it doesn't know anything about the configuration. If we did have the configuration, we have no way to extract arbitrary block attribute assignment expressions from deep within a configuration body, and it's even harder with nested object attribute assignment.

    I agree that this type of analysis could be useful, even beyond hints in the plan output, but it's not clear if there's a path to get the hints reliably into the UI with an acceptable amount of engineering time.

  2. ritz-p commented on Sep 30, 2026

    @ritz-p
    Author

    @jbardin
    Thank you for the detailed explanation!
    I hadn’t realized that the plan renderer doesn’t have access to the configuration expressions.
    From a user’s perspective, hints for straightforward cases would still be useful, even if they were omitted whenever the source couldn’t be determined reliably.
    Are there any plans to improve the plan output to make it easier to understand, particularly when values are unknown until apply?

  3. jbardin commented on Oct 1, 2026

    @jbardin
    Member

    Even if we were to carry along the configuration, what I was also trying to get at is that the configuration doesn't have a way to extract arbitrary expressions from nested assignments based on the final value; the evaluation flows in the other direction. I have a feeling it would be quite a large change just to be able to do that in the first place. There may be other ways to go about the idea of representing statically discoverable relationships however, and some experimentation is being done in that area already.

  4. ritz-p commented on Oct 1, 2026

    @ritz-p
    Author

    @jbardin
    Thanks for clarifying this! I now understand why tracing back from the final value to the original expressions would require significant changes. I appreciate you taking the time to clarify this, and it’s encouraging to hear that related ideas are already being explored.
    Would it be okay for me to close this issue, or would you prefer to keep it open for further discussion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions