# How to Terraform Print Output During Deployments to Inspect Variable Values

> Learn how to terraform print output during deployments to inspect variable values. Use output blocks or the terraform console for quick inspection of your Terraform infrastructure.

- Repository: [HashiCorp/terraform](https://github.com/hashicorp/terraform)
- Tags: how-to-guide
- Published: 2026-02-19

---

**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`](https://github.com/hashicorp/terraform/blob/main/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`](https://github.com/hashicorp/terraform/blob/main/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`](https://github.com/hashicorp/terraform/blob/main/internal/terraform/node_output_test.go)).

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

```go
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.

```hcl
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.

```bash
$ 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`](https://github.com/hashicorp/terraform/blob/main/commands.go)) retrieves values from the state and formats them as JSON. This approach bypasses the standard UI formatting for programmatic consumption.

```bash

# 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`](https://github.com/hashicorp/terraform/blob/main/internal/provisioners/provisioner.go)) within a `null_resource`. This technique is useful for inspecting values inside loops or conditional logic.

```hcl
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:

- **[`internal/terraform/ui_output.go`](https://github.com/hashicorp/terraform/blob/main/internal/terraform/ui_output.go)** – Defines the `UIOutput` interface used for all console writes
- **[`internal/terraform/transform_output.go`](https://github.com/hashicorp/terraform/blob/main/internal/terraform/transform_output.go)** – Implements the `OutputTransformer` that builds output evaluation nodes
- **[`internal/terraform/node_output_test.go`](https://github.com/hashicorp/terraform/blob/main/internal/terraform/node_output_test.go)** – Contains test suites demonstrating how `NodeApplyableOutput` resolves and prints values
- **[`commands.go`](https://github.com/hashicorp/terraform/blob/main/commands.go)** – Registers the `terraform output` CLI command
- **[`internal/provisioners/provisioner.go`](https://github.com/hashicorp/terraform/blob/main/internal/provisioners/provisioner.go)** – Base interface for provisioners like `local-exec` that emit custom output

## 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`](https://github.com/hashicorp/terraform/blob/main/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`](https://github.com/hashicorp/terraform/blob/main/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`](https://github.com/hashicorp/terraform/blob/main/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.