Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 8 min read

Terraform Error: 'Output refers to sensitive values' Missing sensitive = true

Quick answer

Fix Terraform's 'Output refers to sensitive values' error: mark outputs sensitive = true, understand sensitivity propagation, and safely surface secrets without leaking them to logs.

  • #terraform
  • #iac
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Exact Error Message


│ Error: Output refers to sensitive values

│   on outputs.tf line 1:
│    1: output "db_password" {

│ To reduce the risk of accidentally exporting sensitive data that was
│ intended to be only internal, Terraform requires that any root module
│ output containing sensitive data be explicitly marked as sensitive, to
│ confirm your intent.

│ If you do intend to export this data, annotate the output value as
│ sensitive by adding the following argument:
│     sensitive = true

What It Means

Terraform tracks sensitivity through expressions. When a value is marked sensitive — a variable with sensitive = true, a resource attribute the provider flags as sensitive (like aws_db_instance.password), or the result of sensitive() — that sensitivity propagates to anything derived from it. If such a value flows into a root module output that is not itself marked sensitive, Terraform refuses to plan. It is protecting you from accidentally printing a secret into plan output, state summaries, or CI logs.

This is intentional friction, not a bug. Terraform makes you confirm that exporting the value is deliberate by adding sensitive = true to the output.

Common Causes

  • An output references a resource attribute the provider marks sensitive (passwords, private keys, tokens).
  • The output is built from a variable declared with sensitive = true.
  • A value wrapped with the sensitive() function flows into the output.
  • A module output is sensitive, and a root output consumes it without re-declaring sensitivity.
  • String interpolation embeds a sensitive value into a larger output (for example a connection string).

Diagnostic Commands

Validate to confirm which output triggers the error:

terraform validate

Run a plan to see the full sensitivity message and the offending output line:

terraform plan

Search for outputs and any sensitive markings to trace propagation:

grep -rn "output\|sensitive" outputs.tf variables.tf modules/

Inspect the current sensitive output values after apply (explicit read required):

terraform output db_password

Step-by-Step Resolution

  1. If you genuinely intend to export the value, mark the root output sensitive. Terraform then redacts it from plan and apply output:
output "db_password" {
  value     = aws_db_instance.main.password
  sensitive = true
}
  1. For an output assembled from a sensitive input, add the same annotation. Sensitivity of any operand makes the whole expression sensitive:
output "connection_string" {
  value     = "postgres://admin:${var.db_password}@${aws_db_instance.main.address}/app"
  sensitive = true
}
  1. If the value does not actually need to be secret and you want it visible, override the sensitivity explicitly with nonsensitive() — but only when you are certain it is safe:
output "db_endpoint" {
  value = nonsensitive(aws_db_instance.main.endpoint)
}
  1. When the sensitivity comes from a child module output, mark that module output sensitive first, then the root output that consumes it:
# modules/database/outputs.tf
output "password" {
  value     = random_password.db.result
  sensitive = true
}
  1. Validate and plan to confirm the error clears and the value is redacted:
terraform validate
terraform plan
Changes to Outputs:
  + db_password = (sensitive value)
  1. Read the value deliberately only when needed, rather than exposing it in general output:
terraform output -raw db_password

Prevention

  • Mark any output carrying a password, key, or token with sensitive = true from the start.
  • Declare secret input variables with sensitive = true so sensitivity propagates automatically to derived outputs.
  • Propagate sensitivity through module boundaries: sensitive module outputs should stay sensitive at the root.
  • Reserve nonsensitive() for values that are provably safe to reveal, and document why each use is acceptable.
  • Avoid embedding secrets in larger strings you intend to display; keep secret and non-secret outputs separate.
  • Invalid value for variable — a validation block on a sensitive variable rejected the input.
  • Sensitive value in an insecure context — a sensitive value was used somewhere it would be exposed, such as a resource count.
  • Output refers to sensitive values on a module output — the same rule applied one level down.
  • Attempt to output a sensitive value in provisioners or local_file — writing a secret to a place that would leak it.

Frequently Asked Questions

Why does Terraform force me to mark the output sensitive? Because the value is derived from something already marked sensitive. Requiring sensitive = true confirms you intend to export the secret and prevents it from leaking into plan output or logs by accident.

What does sensitive = true actually change? Terraform redacts the value as (sensitive value) in plan and apply output and in terraform output without -raw. The value is still stored in plaintext in state, so protect your state backend.

How do I read a sensitive output when I really need it? Use terraform output -raw <name> to print the unredacted value on demand. For prompts that generate secret-safe Terraform modules, see the Terraform prompt library.

Is it ever safe to use nonsensitive()? Only when you are certain the specific value is not actually secret — for example an endpoint hostname the provider over-marked. Never wrap real credentials in nonsensitive().

Where can I find more Terraform output and state fixes? See the Terraform guides for related output, variable, and state troubleshooting.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.