How to Terraform Print Output During Deployments to Inspect Variable Values

Terraform exposes variable values and computed attributes through output blocks that are automatically printed after apply, or via the terraform console command for interactive inspection, with the underlying architecture using the UIOutput interface and NodeApplyableOutput execution nodes to render values to the terminal.

When you need to inspect values during infrastructure deployments, understanding how to effectively terraform print output values becomes critical for debugging. The hashicorp/terraform source code reveals a structured flow where output values traverse from HCL declarations through graph nodes to the terminal UI via the UIOutput abstraction. By leveraging the built-in output system and debugging utilities defined in the core execution engine, you can expose any variable, resource attribute, or computed value at the appropriate stage of your deployment pipeline.

How Terraform Output Printing Works

The terraform print output mechanism relies on a pipeline that transforms your HCL output blocks into executable graph nodes. When you run terraform apply, the core execution engine resolves these values and routes them through dedicated UI interfaces to your terminal.

The UIOutput Interface and Execution Flow

At the foundation of Terraform's console output lies the UIOutput interface defined in internal/terraform/ui_output.go. This abstraction handles all string writes to the console, including warnings and standard output from your deployment. The interface decouples the core logic from the presentation layer, ensuring that output values can be rendered consistently across different CLI environments.

OutputTransformer and NodeApplyableOutput

The transformation from HCL to printed text occurs in internal/terraform/transform_output.go, where the OutputTransformer adds specialized nodes to the execution graph. Each output block becomes a NodeApplyableOutput node (implementation details referenced in internal/terraform/node_output_test.go).

When the graph executes, each node performs a resolution sequence:

func (n *NodeApplyableOutput) Execute(ctx Context) {
    // Resolve the output value from the state…
    val := ctx.State.OutputValue(n.Addr)
    // Send to UI
    ctx.UI.Output(val.String())
}

This execution pattern ensures that output values are fetched from the state and printed via the UIOutput interface immediately after the apply phase completes successfully.

Methods to Print and Inspect Values

Terraform provides multiple pathways to inspect values depending on whether you need immediate feedback, post-deployment visibility, or runtime debugging during resource creation.

Using Output Blocks for Post-Apply Visibility

Standard output blocks in your HCL configuration automatically appear in the console after a successful apply. These are defined in your configuration files and processed by the OutputTransformer mentioned above.

output "instance_ip" {
  description = "Public IP of the EC2 instance"
  value       = aws_instance.example.public_ip
}

After running terraform apply, you will see:


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

Outputs:

instance_ip = "34.212.12.34"

Note that values marked as sensitive are deliberately suppressed in the standard output to prevent secret leakage, though they remain accessible via terraform output -json if you have state file access.

Interactive Debugging with terraform console

For ad-hoc inspection without modifying your HCL files, the terraform console command provides a REPL environment that evaluates expressions using the same engine as output blocks. This tool allows you to peek at variable values and resource attributes before committing them to your configuration.

$ terraform console
> var.instance_type
"t3.medium"
> aws_instance.example.public_ip
"34.212.12.34"

The console evaluates expressions against your current state and configuration, making it ideal for verifying complex interpolations or data source results.

Machine-Readable Output with terraform output

When integrating with CI/CD pipelines or scripts, the terraform output command (registered in commands.go) retrieves values from the state and formats them as JSON. This approach bypasses the standard UI formatting for programmatic consumption.


# In a GitHub Actions step

IP=$(terraform output -json instance_ip | jq -r .)
echo "Deployed instance IP: $IP"

Behind the scenes, this command retrieves the state, resolves output values, and marshals them through the same UIOutput path used during interactive applies.

Runtime Debugging with null_resource and local-exec

To print values during the resource graph execution—before the final state is written—you can use the local-exec provisioner (defined in internal/provisioners/provisioner.go) within a null_resource. This technique is useful for inspecting values inside loops or conditional logic.

resource "null_resource" "debug" {
  triggers = {
    always = timestamp()
  }

  provisioner "local-exec" {
    command = <<EOT
      echo "DEBUG: instance ID = ${aws_instance.example.id}"
      echo "DEBUG: var.my_var = ${var.my_var}"
    EOT
    interpreter = ["bash", "-c"]
  }
}

This resource executes during the apply phase and prints directly to the console log at the specific point in the dependency graph where it runs.

Key Source Files and Architecture

Understanding the following files in the hashicorp/terraform repository clarifies how output values flow from configuration to terminal:

Summary

  • Standard output blocks automatically terraform print output values after successful applies via the NodeApplyableOutput execution node
  • Sensitive outputs are suppressed from the standard UI but remain accessible through terraform output -json with appropriate state file permissions
  • terraform console provides interactive inspection without HCL modifications, using the same expression engine as output blocks
  • local-exec provisioners enable runtime debugging during graph execution, useful for intermediate value inspection
  • All console output flows through the UIOutput interface defined in internal/terraform/ui_output.go

Frequently Asked Questions

Why isn't my sensitive output printing to the console?

Terraform deliberately suppresses sensitive outputs in the standard CLI output to prevent accidental secret exposure in logs. According to the implementation in internal/terraform/transform_output.go, sensitive values are filtered from the UIOutput stream during standard applies. You can still retrieve these values using terraform output -json <name> if you have access to the state file, or by temporarily removing the sensitive = true flag during debugging (never commit sensitive values to version control).

Can I print values during terraform plan instead of apply?

Standard output blocks only render after a successful apply because they depend on state resolution. However, you can inspect values during the plan phase using terraform console, which evaluates expressions against the proposed state without modifying infrastructure. For values that depend on computed attributes (like resource IDs), you must wait until after the apply phase when these values are known and stored in the state.

How do I print values from inside a module to the root configuration?

To surface values from a child module, you must explicitly define an output block in the module's HCL files, then reference that output in the root module's output block or resource arguments. The OutputTransformer in internal/terraform/transform_output.go processes module outputs separately, and they only become visible to the parent module when explicitly exposed. There is no automatic inheritance of internal module values.

Is there a way to print debug messages without adding null_resource blocks?

While null_resource with local-exec is the most common pattern for runtime debugging, you can also use the TF_LOG environment variable to enable detailed logging of Terraform's internal operations. Setting TF_LOG=DEBUG exposes the decision-making process of the graph walker and resource evaluation, though this produces significantly more verbose output than targeted print statements. For targeted value inspection without permanent resource definitions, terraform console remains the recommended approach.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →