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 — 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 — which 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.