Quick Answer
Set TF_LOG=DEBUG (or TRACE for maximum detail) and TF_LOG_PATH=terraform.log as environment variables before running any Terraform command. Logs include API calls, provider operations, and internal state changes.
Log Levels
| Level | What You Get | When to Use |
|---|---|---|
TRACE | Everything — API payloads, internal state, provider debug | Deep debugging, filing bug reports |
DEBUG | API calls, provider operations, detailed errors | Most debugging scenarios |
INFO | High-level operation info | General monitoring |
WARN | Potential issues, deprecations | Catching problems early |
ERROR | Only errors | Production CI/CD logs |
Enable Logging
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
One-Liner (Linux/macOS)
TF_LOG=DEBUG terraform plan 2>&1 | tee terraform-debug.log
Provider-Specific Logging (Terraform 0.15+)
# Log only the core (skip provider noise)
export TF_LOG_CORE=DEBUG
export TF_LOG_PROVIDER=ERROR
# Or log only the provider (skip core)
export TF_LOG_CORE=ERROR
export TF_LOG_PROVIDER=DEBUG
export TF_LOG_PATH="terraform-debug.log"
terraform apply
This is useful when you know the issue is in the provider (API call failing) vs. Terraform core (state or HCL parsing).
Reading Log Output
Typical DEBUG Output
2026-04-21T10:30:15.123Z [DEBUG] provider.terraform-provider-aws:
HTTP Request Sent: method=POST url=https://ec2.us-east-1.amazonaws.com
2026-04-21T10:30:15.456Z [DEBUG] provider.terraform-provider-aws:
HTTP Response Received: status=200
2026-04-21T10:30:15.789Z [DEBUG] dag/walk: vertex "aws_instance.web" is waiting
What to Look For
| Pattern | Meaning |
|---|---|
HTTP Request Sent | API call being made |
HTTP Response Received: status=4xx | Authentication or permission error |
HTTP Response Received: status=5xx | AWS/Azure/GCP service error |
waiting on dependency | Resource blocked by another |
plugin crashed | Provider binary error |
Crash Logs
When Terraform crashes, it writes a crash log automatically:
# Find crash logs
ls crash.log
ls crash-*.log
# These contain stack traces — attach to bug reports
Logging in CI/CD
# GitLab CI example
plan:
script:
- export TF_LOG=WARN
- export TF_LOG_PATH=terraform.log
- terraform plan -out=plan.tfplan
artifacts:
paths:
- terraform.log
when: on_failure
# GitHub Actions
- name: Terraform Plan
env:
TF_LOG: WARN
TF_LOG_PATH: terraform.log
run: terraform plan
Make Logging Permanent
Bash
# Add to ~/.bashrc or ~/.bash_profile
export TF_LOG="DEBUG"
export TF_LOG_PATH="$HOME/terraform-debug.log"
PowerShell
# Add to $PROFILE
$env:TF_LOG = "DEBUG"
$env:TF_LOG_PATH = "$HOME\terraform-debug.log"
Disable Logging
unset TF_LOG
unset TF_LOG_PATH
unset TF_LOG_CORE
unset TF_LOG_PROVIDER
Security Considerations
- Logs may contain secrets — API keys, passwords, tokens appear in TRACE logs
- Don’t commit log files — add
*.logto.gitignore - Rotate logs — TRACE logs can grow to hundreds of MB quickly
- CI artifacts — set
when: on_failureto only keep logs on errors
Hands-On Courses
Related Articles
Conclusion
TF_LOG=DEBUG with TF_LOG_PATH is your first move when debugging any Terraform issue. Use TF_LOG_CORE and TF_LOG_PROVIDER to isolate problems. In CI/CD, log at WARN level and save artifacts only on failure. Always check for secrets before sharing logs.




