How to fix Error: Sensitive value not allowed in for_each in Terraform

TerraformINTERMEDIATEMEDIUMUpdated Dec 31, 2025ยท 142 views

Terraform prevents sensitive values from being used directly in for_each loops because they would be exposed as resource instance keys. Learn how to use nonsensitive(), split keys, or switch to count to work around this constraint.

Quick fix

Fixes Error: Sensitive value not allowed in for_each

variable "api_keys" {
  type      = map(string)
  sensitive = true
  default = {
    key1 = "secret-value-1"
    key2 = "secret-value-2"
  }
}

resource "aws_resource" "example" {
  for_each = nonsensitive(toset(keys(var.api_keys)))

  name  = each.value
  value = var.api_keys[each.key]  # Value remains sensitive
}
  1. Use nonsensitive() to unwrap non-sensitive iteration values
  2. Split sensitive and non-sensitive data into separate variables
  3. Use count instead of for_each when necessary
  4. Extract keys from sensitive objects using local values
terraform โ€” error
variable "api_keys" {
type = map(string)
sensitive = true
default = {
key1 = "secret-value-1"
key2 = "secret-value-2"
}
}
resource "aws_resource" "example" {
for_each = nonsensitive(toset(keys(var.api_keys)))
name = each.value
value = var.api_keys[each.key] # Value remains sensitive
}
Error: Sensitive value not allowed in for_each

What this error means

Terraform treats values as sensitive when they come from sensitive input variables, secret management systems, or resource outputs marked as sensitive. Because for_each uses iteration values as unique identifiers for resource instances, these identifiers are always displayed in plans, logs, and state files. To prevent accidentally exposing sensitive data (like API keys, passwords, or database credentials), Terraform explicitly forbids sensitive values in for_each expressions. The error occurs at plan time when Terraform evaluates your configuration and determines that a value you're trying to iterate over contains sensitive information. This is a safety feature, not a limitation you should work around with caution.

Typical symptoms

  • Error message states 'Sensitive value not allowed in for_each'
  • Error occurs during terraform plan or apply
  • The problematic variable is marked sensitive=true or comes from a sensitive output
  • Error points to the for_each line in your resource or module configuration

Common causes

  1. Using a sensitive input variable directly in a for_each expression
  2. Iterating over an object that contains sensitive values from another module or data source
  3. Using sensitive output values in for_each without extracting non-sensitive keys first
  4. Passing sensitive values through functions that don't extract non-sensitive attributes (like keys())

How to fix "Error: Sensitive value not allowed in for_each"

1Use nonsensitive() to unwrap non-sensitive iteration values

If only the keys or non-sensitive parts of your variable need to be used in for_each, wrap them with the nonsensitive() function (available in Terraform v0.15+). This tells Terraform that the iteration value itself is not sensitive, even if it derives from a sensitive source.

hcl
variable "api_keys" {
  type      = map(string)
  sensitive = true
  default = {
    key1 = "secret-value-1"
    key2 = "secret-value-2"
  }
}

resource "aws_resource" "example" {
  for_each = nonsensitive(toset(keys(var.api_keys)))

  name  = each.value
  value = var.api_keys[each.key]  # Value remains sensitive
}

The key insight is that keys() extracts non-sensitive identifiers, and nonsensitive() confirms to Terraform that these keys are safe to use as for_each iteration values.

2Split sensitive and non-sensitive data into separate variables

Structure your input variables so that keys and non-sensitive metadata are in one variable, while sensitive values are in another. This avoids marking the entire structure as sensitive and lets you iterate freely over the keys.

hcl
variable "resource_names" {
  type    = set(string)
  default = ["database", "cache", "queue"]
}

variable "api_keys" {
  type      = map(string)
  sensitive = true
  default = {
    database = "secret-db-key"
    cache    = "secret-cache-key"
    queue    = "secret-queue-key"
  }
}

resource "aws_resource" "example" {
  for_each = var.resource_names

  name  = each.value
  value = var.api_keys[each.value]  # Lookup in sensitive map
}

This pattern is often the cleanest because your loop variable is non-sensitive by design.

3Use count instead of for_each when necessary

If your data structure must remain as a single sensitive object, switch from for_each to count. While less flexible, count works with sensitive values.

hcl
variable "services" {
  type = map(object({
    name = string
    key  = string
  }))
  sensitive = true
}

locals {
  service_list = values(var.services)
}

resource "aws_resource" "example" {
  count = length(local.service_list)

  name  = local.service_list[count.index].name
  value = local.service_list[count.index].key
}

Note: With count, you reference resources by index (aws_resource.example[0], aws_resource.example[1], etc.) rather than by key, which can be less intuitive.

4Extract keys from sensitive objects using local values

Use a local value to transform your sensitive data, extracting only the keys you need for iteration. This separates the sensitive data retrieval from the iteration logic.

hcl
variable "secret_config" {
  type      = map(object({ value = string }))
  sensitive = true
}

locals {
  config_keys = nonsensitive(keys(var.secret_config))
}

resource "aws_resource" "example" {
  for_each = toset(local.config_keys)

  name  = each.value
  value = var.secret_config[each.value].value
}

This approach makes it explicit where sensitive data enters the configuration and where safe iteration happens.

5Verify the fix with terraform plan

After applying one of the above solutions, run terraform plan to ensure the configuration is valid and no sensitive values are exposed in the output.

bash
terraform plan -out=tfplan

Check that:
- The plan completes without the "Sensitive value not allowed" error
- Sensitive values appear as "(sensitive)" in the plan output, not as plaintext
- Resource instances are created with the expected naming scheme
- No secrets leak into terraform logs

If you still see issues, verify that your nonsensitive() or keys() function is properly extracting the safe values.

Advanced notes

Terraform's handling of sensitive values evolved significantly:
- Terraform 0.14 introduced strict sensitive value tracking and blocked their use in for_each
- Terraform 0.15 added the nonsensitive() function to explicitly unwrap sensitive values
- Terraform 1.6 introduced a regression where sensitive values in conditions combined with for_each started failing in some cases

If you're using Terraform 1.5 or earlier, some solutions may not work. Consider upgrading to Terraform 1.6+ for the best handling of sensitive data. Additionally, be cautious when using nonsensitive() - it removes the safety flag, so only use it on values that truly aren't sensitive.

Frequently asked questions

What does "Error: Sensitive value not allowed in for_each" mean?
Terraform treats values as sensitive when they come from sensitive input variables, secret management systems, or resource outputs marked as sensitive. Because for_each uses iteration values as unique identifiers for resource instances, these identifiers are always displayed in plans, logs, and state files. To prevent accidentally exposing sensitive data (like API keys, passwords, or database credentials), Terraform explicitly forbids sensitive values in for_each expressions.
How do I fix "Error: Sensitive value not allowed in for_each"?
Terraform prevents sensitive values from being used directly in for_each loops because they would be exposed as resource instance keys. Learn how to use nonsensitive(), split keys, or switch to count to work around this constraint.
What causes "Error: Sensitive value not allowed in for_each"?
Using a sensitive input variable directly in a for_each expression Iterating over an object that contains sensitive values from another module or data source Using sensitive output values in for_each without extracting non-sensitive keys first
Is the "Error: Sensitive value not allowed in for_each" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading