How do you debug a failing or unexpected Terraform run — what do `terraform console`, `terraform graph`, `terraform show`, and `TF_LOG` give you?

5 minadvancedterraformdebuggingcli

Quick Answer

terraform console opens a read-eval-print loop for evaluating arbitrary HCL expressions against the current state, useful for testing a tricky for expression or function call without a full apply. terraform graph emits the dependency graph in DOT format (renderable with Graphviz), helpful for visualizing why Terraform ordered operations the way it did. terraform show prints the current state (or a saved plan file) in human-readable or JSON form, useful for scripting or inspecting exactly what's recorded for a resource. For deeper issues — a provider crash, a mysterious hang — setting TF_LOG=DEBUG (or TRACE for maximum verbosity, optionally with TF_LOG_PATH to write to a file) surfaces the underlying provider RPC calls and HTTP requests Terraform Core is making, which is usually where the real root cause is found.

Detailed Answer

When a Terraform run does something unexpected — an odd diff, a provider error, a hang — there's a specific toolkit to reach for before guessing, each surfacing a different layer of what's actually happening.

terraform console

$ terraform console
> local.subnet_ids
["subnet-aaa", "subnet-bbb"]
> [for s in var.subnets : s.id if s.public]
["subnet-aaa"]

An interactive REPL evaluating any HCL expression against the current configuration/state. It's the fastest way to check whether a for expression, function call, or reference actually evaluates to what you expect, without running a full plan.

terraform graph

terraform graph | dot -Tsvg > graph.svg

Emits the resource dependency graph in DOT format. Rendered with Graphviz, this visualizes exactly which resources depend on which, useful when a plan's execution order seems wrong, or to understand why two resources aren't being created in parallel (there's likely a dependency edge, implicit or explicit, connecting them).

terraform show

terraform show                          # current state, human-readable
terraform show -json                    # current state as JSON, for scripting
terraform show tfplan                    # a saved plan file, human-readable

Prints exactly what Terraform currently has recorded, either the live state or a saved plan. This is the ground truth to check against when a plan's summary line doesn't match your expectations for a specific resource's attributes.

TF_LOG environment variable

TF_LOG=DEBUG TF_LOG_PATH=terraform.log terraform apply

Levels from least to most verbose: TRACE, DEBUG, INFO, WARN, ERROR. DEBUG/TRACE reveal the actual RPC calls Terraform Core makes to each provider plugin, and the underlying HTTP requests/responses the provider makes to the real API. This is where you find out, for example, that a request timed out, or that the API returned an error message Terraform's own output summarized too tersely.

Putting it together

A practical debugging sequence: use console to sanity-check any suspicious expression first (fast, cheap); use show/graph to inspect what Terraform currently believes about state and ordering; and only reach for TF_LOG when the problem seems to be happening inside a provider's API interaction rather than in your own configuration logic.