When you hit a mysterious failure or unexplained drift in Terraform, the first move is to enable verbose logging with the TF_LOG family of environment variables.
Log volume tends to balloon, though, and mishandling the configuration can drag out investigations or leak sensitive data. This article organizes safe log capture procedures, key reading techniques, and exam-relevant points from a practitioner's perspective.
Terraform enables verbose logging via the TF_LOG environment variable. Valid values are TRACE, DEBUG, INFO, WARN, and ERROR — the lower the level, the more verbose. For routine troubleshooting use DEBUG; reserve TRACE for when you need to dig deeper. Logs go to stderr by default, but TF_LOG_PATH writes them to a file.
For finer-grained control, use TF_LOG_CORE (Terraform core) and TF_LOG_PROVIDER (provider plugins). Anything you don't set falls back to TF_LOG as the default; per-component settings take precedence. Verbose logs may contain fragments of API requests, so handle them with care.
| Environment variable | Scope | Primary use | Notes |
|---|---|---|---|
| TF_LOG | Core + providers (everything) | Quickly grasp the whole picture | Also serves as the default for anything not explicitly set |
| TF_LOG_CORE | Terraform core processing | Track state transitions, diff computation, and backend behavior | When set, this takes precedence for core |
| TF_LOG_PROVIDER | Provider plugins | Track API calls and attribute mapping | When set, this takes precedence for providers |
| TF_LOG_PATH | Output file | Save logs to a file | Appends to existing files (you handle rotation yourself) |
Flow of Terraform verbose logs (what gets emitted where)
Basic enablement (Linux/macOS, Windows)
# Linux/macOS
export TF_LOG=DEBUG
export TF_LOG_PATH=./terraform-debug.log
terraform plan
# Windows (PowerShell)
$env:TF_LOG = "DEBUG"
$env:TF_LOG_PATH = "./terraform-debug.log"
terraform plan
# Disable when finished
unset TF_LOG TF_LOG_PATH # PowerShell: Remove-Item Env:TF_LOG, Env:TF_LOG_PATHStart with a minimal directory that reproduces the issue, capture DEBUG-level logs, and work through isolation. TRACE is a last resort — switch to it right before the section of interest to keep the output readable.
In CI/CD, give each job its own TF_LOG_PATH and clearly define log rotation and retention. Suppress color output with -no-color to improve log readability.
Standard repro log procedure (Bash example)
set -euo pipefail
export TF_LOG=DEBUG
export TF_LOG_PATH="./repro-$(date +%Y%m%d-%H%M%S).log"
terraform init -upgrade
terraform plan -no-color
# Only if the problem doesn't surface in plan: enable TRACE for the focused section before apply
export TF_LOG=TRACE
terraform apply -refresh-only -no-color # Minimize side effects and verify diff only
# Cleanup
env -u TF_LOG -u TF_LOG_PATH true >/dev/null 2>&1 || trueRead logs in chronological order. Start from the WARN/ERROR right before the failure and trace backward through nearby DEBUG lines — that's the fastest way to pin down causality. For provider calls, correlate by resource address (e.g., module.db.aws_db_instance.this) and RPC direction (request/response).
When the diff doesn't match expectations, focus on how Unknown values are handled in plan (computed attributes) and on normalization that happens after read (refresh/re-running plan). Trim noisy TRACE output with grep and extract only the lines for the resource of interest to follow the thread.
Log filtering examples (grep/awk)
# Filter by resource address
grep -F "module.db.aws_db_instance.this" terraform-debug.log | less
# Inspect surroundings by level and timestamp
awk '/ERROR|WARN|DEBUG/ {print}' terraform-debug.log | less
# Verify request/response pairs
grep -E "(request|response)" terraform-debug.log | grep aws_db_instance | lessWhen core seems fine but the API layer is suspect, bump TF_LOG_PROVIDER to DEBUG/TRACE while holding TF_LOG_CORE down at INFO or WARN — that cuts the noise. You suppress the diff computation details while still focusing on HTTP-equivalent exchanges and the flow of attribute application.
On Windows or in CI, temporarily flip the scope so only the moments right before and after the problem area run at a high level — this prevents log bloat.
Per-scope log control (PowerShell and Bash)
# PowerShell
$env:TF_LOG_CORE = "WARN"
$env:TF_LOG_PROVIDER = "DEBUG"
$env:TF_LOG_PATH = "./provider-only.log"
terraform plan
# Bash
export TF_LOG_CORE=INFO
export TF_LOG_PROVIDER=TRACE
export TF_LOG_PATH=./provider-trace.log
terraform apply -refresh-only -no-colorAuthentication errors: when core succeeds but the provider's requests are rejected, provider-side DEBUG/TRACE reveals clues about credential detection, endpoints, and scopes. Also check the resolution order of profiles and environment variables.
Unstable diffs: suspect data source read order or drift from external changes, and compare stability via refresh-only and a re-run of plan. Also verify whether provider normalization logic is rounding attributes.
Minimum stability comparison procedure (Bash)
export TF_LOG=DEBUG
export TF_LOG_PATH=./stability-compare.log
terraform plan -no-color
terraform apply -refresh-only -no-color
terraform plan -no-color
# Compare the three steps to identify unstable areasThe Associate and Pro exams frequently test the roles of TF_LOG / TF_LOG_CORE / TF_LOG_PROVIDER / TF_LOG_PATH, the meaning of each log level, the fact that output goes to stderr, and combined use with -no-color. Be ready to articulate when to use which.
For Terraform Cloud/Enterprise remote runs, TF_LOG only affects local CLI behavior — the actual execution is in the remote run logs. In CI, standardize per-job file output, retention periods, and the secret-masking procedure.
Safe capture in CI (e.g., GitHub Actions step excerpt)
- name: Terraform Plan (debug log)
env:
TF_LOG: DEBUG
TF_LOG_PATH: terraform-${{ github.run_id }}.log
run: |
terraform init -input=false
terraform plan -no-color -input=false
# Store as an artifact and protect secret strings with a masking policyAssociate / Pro
問題 1
While isolating a bug, you want to keep Terraform's diff computation quiet but follow the provider plugins in detail, and you want logs saved to a file. Which is the most appropriate configuration?
正解: A
The requirement is to detail only the provider while keeping core quiet, so TF_LOG_PROVIDER=DEBUG with TF_LOG_CORE=INFO fits, and TF_LOG_PATH satisfies the file-save requirement. B makes core verbose too. C is global TRACE — far too much noise. D fails the detail requirement.
I set TF_LOG but nothing (or very little) is being printed — why?
It may be going to stderr — check your shell redirection and log collection settings. Also review whether you've suppressed noise via TF_LOG_CORE or TF_LOG_PROVIDER set to a lower level.
Can the logs contain sensitive information?
Terraform masks some values, but provider debug output may contain fragments like endpoints and identifiers. Always follow your organization's policy and redact or remove sensitive data before sharing.
Can TF_LOG capture verbose logs from Terraform Cloud remote runs?
TF_LOG only affects the local CLI. For remote runs, refer to the run logs in Terraform Cloud/Enterprise. You can still use TF_LOG locally to capture supplementary logs for plan submission and configuration resolution if needed.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...