100+ Terraform commands for init, plan, apply, state, workspaces, import, and more. Includes an Error Message Lookup section. Verified against official HashiCorp docs.
Everything runs in your browser. No commands or data are sent to any server.
Paste the error you are seeing and find the command that fixes it. These are the most searched Terraform errors on Stack Overflow with combined views in the millions.
Error acquiring the state lock: ConditionalCheckFailedException What it means
Another Terraform process is holding the state lock in DynamoDB. This happens when a previous run crashed or was interrupted without releasing the lock.
Fix
terraform force-unlock <LOCK_ID> Gotcha
Get the LOCK_ID from the error message output. Only run this if you are certain no other legitimate Terraform process is running. Check your DynamoDB lock table first.
Error: Provider configuration not present What it means
Your state file references a provider that is no longer configured in your current Terraform files. Usually happens after reorganizing code or moving resources between modules.
Fix
terraform init -upgrade Gotcha
If init does not fix it you may need to remove the orphaned provider from state with terraform state rm.
Error: Required plugins are not installed What it means
The .terraform.lock.hcl file exists but the actual provider binaries are missing from .terraform/providers. Common after cloning a repo or cleaning the directory.
Fix
terraform init Gotcha
Always run terraform init after cloning a repo or after any change to required_providers blocks.
Error: Conflicting configuration arguments What it means
Two arguments in the same resource block are mutually exclusive. Common with security group rules that have both inline rules and separate rule resources.
Fix
terraform validate Gotcha
Run terraform validate to get the exact line and argument names. Remove one of the conflicting arguments from the resource block.
No changes. Your infrastructure matches the configuration. What it means
This is not an error. Terraform found the real infrastructure matches what is in your .tf files exactly. Nothing needs to be applied.
Fix
terraform show Gotcha
Run terraform show to see the current state of all managed resources. If you expected changes, check that you saved your .tf files before running plan.
Error: Resource not found in state What it means
You are targeting a resource with -target or trying to import into a resource address that does not exist in your current state.
Fix
terraform state list Gotcha
Run terraform state list to see all resource addresses in state. Copy the exact address including module path if the resource is inside a module.
5 essential commands to get you started. The full reference is right below.
terraform init Run this first in any new Terraform directory, after cloning a repo, or after adding a new provider.
terraform validate Check your configuration for syntax errors and basic logic problems before running plan.
terraform fmt Format all .tf files in the current directory to the canonical Terraform style.
terraform plan Preview every change Terraform will make before making any of them.
terraform apply Apply the changes shown in the last plan to your real infrastructure.
terraform init ↓ Click command to explain
-upgrade Upgrades all providers to the latest version allowed by version constraints -reconfigure Reinitializes the backend, ignoring any existing configuration -backend=false Skips backend initialization When to use this
Run this first in any new Terraform directory, after cloning a repo, or after adding a new provider.
Gotcha
Always run terraform init after any change to required_providers or backend blocks. The most common cause of confusing errors is forgetting this step.
terraform validate ↓ Click command to explain
-json Outputs validation results as JSON for use in CI pipelines When to use this
Check your configuration for syntax errors and basic logic problems before running plan.
Gotcha
Validate only checks syntax and basic logic. It does not check whether your AWS resources actually exist or whether your IAM permissions allow the actions you are requesting.
terraform fmt ↓ Click command to explain
-recursive Formats all .tf files in subdirectories as well -check Exits with a non-zero status if files are not formatted, without changing them (use in CI) -diff Shows the diff of what would change When to use this
Format all .tf files in the current directory to the canonical Terraform style.
Gotcha
Run terraform fmt before every commit. Many teams enforce this in CI with terraform fmt -check and fail the pipeline if files are not formatted.
terraform plan ↓ Click command to explain
-out=tfplan Saves the plan to a file so apply can use the exact same plan -target=resource_type.name Limits the plan to one specific resource -var-file=vars.tfvars Loads variable values from a file -destroy Shows what terraform destroy would do When to use this
Preview every change Terraform will make before making any of them.
Gotcha
Always save the plan with -out=tfplan in CI pipelines so the apply step uses the exact plan that was reviewed. Without -out, a new plan is generated at apply time which may differ from what was reviewed.
terraform apply ↓ Click command to explain
-auto-approve Skips the confirmation prompt (use in CI only) tfplan Applies a previously saved plan file passed as an argument -target=resource_type.name Applies only one specific resource When to use this
Apply the changes shown in the last plan to your real infrastructure.
Gotcha
Never use -auto-approve in manual workflows. Only use it in CI pipelines where the plan has already been reviewed and approved by a human.
terraform destroy ↓ Click command to explain
-auto-approve Skips the confirmation prompt -target=resource_type.name Destroys only one resource When to use this
Destroy all resources managed by the current Terraform configuration.
Gotcha
This permanently deletes real infrastructure and there is no undo. Always run terraform plan -destroy first to see exactly what will be deleted.
terraform plan -destroy ↓ Click command to explain
When to use this
Preview exactly what terraform destroy would delete before actually deleting anything.
terraform output ↓ Click command to explain
-json Outputs all values as JSON for use in scripts -raw Outputs a single value as a plain string with no quotes (use in shell scripts) output_name Shows only that specific output value When to use this
Read the output values from a completed apply, such as a load balancer URL or database endpoint.
Gotcha
Outputs are only available after a successful apply. If you just ran init or plan, there are no outputs yet.
terraform show ↓ Click command to explain
-json Outputs state as JSON for use in scripts tfplan Shows what a saved plan file would do When to use this
Display the current state of all managed resources in a human readable format.
terraform refresh ↓ Click command to explain
When to use this
Sync the Terraform state file with the real state of your infrastructure without making any changes.
Gotcha
terraform refresh is deprecated as a standalone command in recent Terraform versions. Use terraform apply -refresh-only instead, which shows you what would change in state before committing.
terraform apply -refresh-only ↓ Click command to explain
When to use this
Update the state file to match the real infrastructure without making any infrastructure changes.
terraform graph | dot -Tsvg > graph.svg ↓ Click command to explain
When to use this
Generate a visual dependency graph of all resources showing which resources depend on which others.
Gotcha
Requires graphviz to be installed locally. The output is dot format and must be piped to a renderer.
terraform version ↓ Click command to explain
When to use this
Check which version of Terraform is installed and which providers are being used.
terraform plan -json ↓ Click command to explain
When to use this
Stream the plan as structured JSON for tooling that renders or analyzes plan output, such as CI dashboards or policy checks.
Gotcha
The JSON stream is a series of newline-delimited JSON objects, not a single JSON document, so it needs a streaming parser rather than a plain JSON.parse.
terraform apply -json ↓ Click command to explain
When to use this
Stream apply progress as structured JSON, useful for building a custom deployment UI or parsing results in CI.
terraform version -json ↓ Click command to explain
When to use this
Read the Terraform and provider versions programmatically in a script instead of parsing plain text output.
terraform apply -input=false ↓ Click command to explain
When to use this
Run apply in a non-interactive environment such as CI, where there is no terminal available to answer a variable prompt.
Gotcha
If a required variable has no default and no value is supplied, -input=false makes apply fail immediately with a clear error instead of hanging while it waits for input that will never come.
terraform plan -input=false ↓ Click command to explain
When to use this
Run plan in CI where no terminal is available to answer a missing variable prompt.
terraform output -no-color ↓ Click command to explain
When to use this
Print output values without terminal color codes so the result is clean when piped into a log file or another tool.
terraform state list ↓ Click command to explain
-state=path Uses a specific state file instead of the default When to use this
List every resource currently tracked in the Terraform state file.
Gotcha
If you get an error about a resource not existing, run this first to see the exact address including module path.
terraform state show resource_type.name ↓ Click command to explain
When to use this
Show the full attributes of one specific resource as stored in state.
Gotcha
The resource address must match exactly, including module path. Use terraform state list first to find the correct address.
terraform state mv resource_type.old_name resource_type.new_name ↓ Click command to explain
When to use this
Rename a resource in state without destroying and recreating it, or move a resource into or out of a module.
Gotcha
Always run terraform plan after a state mv to confirm Terraform sees the resource correctly in its new location before running apply.
terraform state rm resource_type.name ↓ Click command to explain
When to use this
Remove a resource from state without destroying the real infrastructure, useful when you want Terraform to stop managing a resource.
Gotcha
The real infrastructure is not deleted when you remove it from state. Terraform simply stops tracking it, but the next terraform plan will try to create it again unless you also remove it from your .tf files.
terraform state pull ↓ Click command to explain
When to use this
Download and print the current remote state as JSON, useful for inspecting or backing up state.
terraform state push terraform.tfstate ↓ Click command to explain
When to use this
Upload a local state file to the remote backend, used for disaster recovery.
Gotcha
Pushing an incorrect state file can corrupt your infrastructure tracking. Always back up the current remote state with terraform state pull before pushing.
terraform force-unlock LOCK_ID ↓ Click command to explain
When to use this
Release a stuck state lock when a previous Terraform run crashed and left the lock in DynamoDB.
Gotcha
Only run this if you are absolutely certain no other Terraform process is legitimately holding the lock. Check your DynamoDB lock table first and confirm no other pipeline is running.
terraform state replace-provider old_provider new_provider ↓ Click command to explain
When to use this
Update state to reference a renamed or moved provider without destroying resources.
terraform taint resource_type.name ↓ Click command to explain
When to use this
Mark a resource as tainted so the next apply destroys and recreates it, useful when a resource is broken in a way Terraform cannot detect.
Gotcha
Tainting a resource does not change anything immediately. It only affects the next plan or apply, and in modern Terraform the -replace flag on apply is the recommended alternative since it does not require a separate command run first.
terraform untaint resource_type.name ↓ Click command to explain
When to use this
Undo a taint mark on a resource so the next apply leaves it alone instead of recreating it.
terraform apply -replace=resource_type.name ↓ Click command to explain
When to use this
Force Terraform to destroy and recreate a single resource in one step, the modern replacement for the separate taint command.
Gotcha
This still runs a full plan and apply, so review the plan output before confirming since -replace can be combined with other pending changes in the same apply.
terraform plan -refresh=false ↓ Click command to explain
When to use this
Skip the state refresh step before planning, which speeds up plans significantly in large configurations with many resources.
Gotcha
The plan may miss drift that happened outside Terraform since the last refresh, so only use this for speed in situations where you already trust the current state.
terraform apply -lock=false ↓ Click command to explain
When to use this
Disable state locking during apply, used when the configured backend does not support locking or to work around a stuck lock in an emergency.
Gotcha
Disabling locking removes the safety net that prevents two people from applying at the same time, which can corrupt state if anyone else is running Terraform concurrently.
terraform apply -lock-timeout=5m ↓ Click command to explain
When to use this
Wait up to the given duration for the state lock to become available instead of failing immediately, useful when a previous run is still finishing.
terraform apply -refresh-only -target=resource_type.name ↓ Click command to explain
When to use this
Update state for one specific resource to match reality without touching the rest of the infrastructure or state.
terraform state list -id=i-1234567890abcdef0 ↓ Click command to explain
When to use this
Find which Terraform resource address corresponds to a real cloud resource ID found in a console alert or another team's report.
terraform state rm module.mymodule ↓ Click command to explain
When to use this
Remove every resource inside a module from state at once, such as when deleting a module block but wanting to keep the underlying infrastructure untouched.
Gotcha
This stops Terraform from tracking every resource the module created, so make sure the plan afterward does not try to recreate them because the module block is still present in your configuration.
terraform destroy -target=resource_type.name ↓ Click command to explain
When to use this
Destroy a single resource without touching the rest of the infrastructure managed by the same configuration.
Gotcha
-target is meant for exceptional situations, not routine use. Repeatedly targeting individual resources instead of applying the full configuration can let real infrastructure drift away from what your .tf files describe.
terraform state mv -state-out=new.tfstate resource_type.name resource_type.name ↓ Click command to explain
When to use this
Move a resource out of the current state into a different state file entirely, such as when splitting one large configuration into several smaller ones.
terraform state pull > backup.tfstate ↓ Click command to explain
When to use this
Create a manual local backup of the current remote state before running a risky operation like state rm, state mv, or force-unlock.
Gotcha
Get in the habit of running this before any command that rewrites state directly, since it gives you something to restore from with terraform state push if something goes wrong.
terraform plan -lock=false ↓ Click command to explain
When to use this
Skip acquiring the state lock during plan, useful when a backend does not support locking or when read-only inspection is needed while a lock is held elsewhere.
terraform state show 'module.mymodule.resource_type.name' ↓ Click command to explain
When to use this
Show the attributes of a resource that lives inside a module rather than at the root of the configuration.
Gotcha
The quotes around the module address are required in most shells because the dots and brackets in a nested module path can otherwise be misinterpreted by the shell.
terraform apply -target=resource_type.name1 -target=resource_type.name2 ↓ Click command to explain
When to use this
Apply changes to more than one specific resource by repeating the -target flag, without applying the rest of the configuration.
terraform state list -state=terraform.tfstate.backup ↓ Click command to explain
When to use this
List resources from a specific local state file, such as the automatic .tfstate.backup Terraform writes before overwriting state, instead of the active remote state.
terraform state push -force terraform.tfstate ↓ Click command to explain
When to use this
Override the remote state's serial and lineage checks when pushing, used only when recovering from a corrupted or intentionally divergent local state.
Gotcha
This bypasses the exact safety check that normally prevents you from accidentally overwriting newer state with an older copy, so confirm you actually have the most current state before using -force.
terraform refresh -target=resource_type.name ↓ Click command to explain
When to use this
Sync state for a single resource using the older refresh command, seen in scripts written before apply -refresh-only existed.
Gotcha
Prefer terraform apply -refresh-only -target=resource_type.name in current Terraform versions, since standalone refresh is deprecated and offers no preview of what will change before committing it.
terraform workspace list ↓ Click command to explain
When to use this
List all workspaces. The current one is marked with an asterisk.
terraform workspace new staging ↓ Click command to explain
When to use this
Create a new workspace to manage a separate state for the same configuration, for example dev, staging, and production.
Gotcha
Creating a new workspace does not copy any existing resources. Each workspace has a completely separate state file.
terraform workspace select production ↓ Click command to explain
When to use this
Switch to a different workspace before running plan or apply.
Gotcha
Always check which workspace is active with terraform workspace show before running any destructive commands. Running terraform destroy in production when you thought you were in dev is catastrophic.
terraform workspace show ↓ Click command to explain
When to use this
Print the name of the currently active workspace.
Gotcha
Run this before any destructive operation to confirm you are in the right workspace.
terraform workspace delete staging ↓ Click command to explain
When to use this
Delete a workspace after you have destroyed all its resources.
Gotcha
You must destroy all resources in a workspace before deleting it, and you cannot delete the default workspace.
terraform workspace new -state=path/to/existing.tfstate staging ↓ Click command to explain
When to use this
Create a new workspace pre-populated from an existing state file instead of starting empty, useful when converting a single-workspace setup into multiple workspaces.
terraform workspace select -or-create=staging ↓ Click command to explain
When to use this
Switch to a workspace in a single command, automatically creating it first if it does not already exist, which avoids a separate new step in CI pipelines.
terraform import resource_type.name resource_id ↓ Click command to explain
When to use this
Import an existing real infrastructure resource into Terraform state so Terraform can start managing it.
Gotcha
Importing a resource only updates state. It does not write the corresponding .tf configuration for you. Write the resource block in your .tf files manually before importing, and make sure the configuration matches the real resource or the next plan will show changes.
terraform plan -generate-config-out=generated.tf ↓ Click command to explain
When to use this
Automatically generate the .tf configuration for resources being imported, available in Terraform 1.5 and later.
Gotcha
Generated configuration is a starting point, not a finished product. Always review and clean up the generated .tf file before committing it.
terraform providers lock ↓ Click command to explain
-platform=linux_amd64 Locks for a specific platform When to use this
Generate or update the .terraform.lock.hcl file to pin provider versions for reproducible builds.
Gotcha
The .terraform.lock.hcl file should be committed to git. This was one of the most upvoted Terraform Stack Overflow questions.
terraform providers mirror /path/to/mirror ↓ Click command to explain
When to use this
Download all required providers to a local directory for use in air-gapped or offline environments.
terraform import -var="region=us-east-1" aws_instance.example i-1234567890abcdef0 ↓ Click command to explain
When to use this
Import a resource whose configuration references a variable, so Terraform can evaluate the resource address correctly during the import.
terraform import 'module.mymodule.aws_instance.example' i-1234567890abcdef0 ↓ Click command to explain
When to use this
Import an existing resource directly into a nested module address instead of the root module.
Gotcha
The quotes around the module address are required in most shells, since the dots in a nested module path can otherwise be misinterpreted.
terraform providers mirror -platform=linux_amd64 /path/to/mirror ↓ Click command to explain
When to use this
Download only the provider binaries needed for a specific operating system and architecture, useful when preparing a mirror for a Linux CI runner from a different machine.
terraform plan -generate-config-out=generated.tf -target=aws_instance.example ↓ Click command to explain
When to use this
Generate configuration for a single resource being imported instead of every resource pending import at once.
terraform console ↓ Click command to explain
When to use this
Open an interactive console to evaluate Terraform expressions, test functions, and inspect values before using them in configuration.
Gotcha
Type exit or press Ctrl-D to quit. This is the fastest way to test a complex expression before putting it in your code.
terraform output -json ↓ Click command to explain
When to use this
Get all output values as JSON for use in scripts or to pass values to another tool.
terraform plan -var="environment=staging" ↓ Click command to explain
When to use this
Pass a single variable value on the command line for a quick test without editing a .tfvars file.
Gotcha
For multiple variables, use a .tfvars file with -var-file instead of multiple -var flags.
terraform apply -var-file="production.tfvars" ↓ Click command to explain
When to use this
Apply using variable values from a specific .tfvars file, such as production.tfvars.
Gotcha
Never commit .tfvars files containing secrets to git. Use environment variables or a secrets manager for sensitive values.
terraform show -json | jq '.values.root_module.resources' ↓ Click command to explain
When to use this
Pipe the structured state output into jq to extract exactly the resource attributes you need, without scrolling through the full human-readable show output.
terraform output -raw db_password ↓ Click command to explain
When to use this
Read a single named output value with no surrounding quotes, ready to pipe directly into another command or store in a shell variable.
Gotcha
Terraform still prints sensitive outputs in plain text with -raw. Be careful about where the output ends up, such as shell history or CI logs.
terraform plan -var-file="staging.tfvars" ↓ Click command to explain
When to use this
Preview the changes for a specific environment's variable values before applying, such as checking staging.tfvars separately from production.tfvars.
echo 'aws_instance.example.id' | terraform console ↓ Click command to explain
When to use this
Pipe a single expression into terraform console from a script to evaluate one value without opening an interactive session.
terraform plan -var="region=us-east-1" -var="environment=staging" ↓ Click command to explain
When to use this
Pass several individual variable values by repeating the -var flag, useful for a quick test with more than one override.
terraform get ↓ Click command to explain
-update Downloads the latest version of modules within version constraints When to use this
Download and install all modules referenced in your configuration without reinitializing the backend.
Gotcha
terraform init also runs terraform get. Use terraform get -update specifically when you want to update modules without touching the backend configuration.
terraform providers ↓ Click command to explain
When to use this
Show the provider requirements for the current configuration and which module requires each provider.
terraform init -upgrade ↓ Click command to explain
When to use this
Upgrade all providers and modules to the latest versions allowed by your version constraints.
Gotcha
This updates the .terraform.lock.hcl file. Commit the updated lock file to git so teammates use the same provider versions.
tofu init ↓ Click command to explain
When to use this
OpenTofu is an open source fork of Terraform with an Apache 2.0 license. Its CLI commands are identical to Terraform but use the tofu binary instead of terraform.
Gotcha
If your team is migrating from Terraform to OpenTofu for license reasons, every command in this cheat sheet works identically with tofu replacing terraform in the command.
terraform providers schema -json ↓ Click command to explain
When to use this
Dump every resource and data source argument for every provider in the configuration as JSON, useful for tooling, documentation generation, or checking exactly what a resource type accepts.
terraform init -plugin-dir=/path/to/local/providers ↓ Click command to explain
When to use this
Initialize using providers from a local directory instead of the registry, used in air-gapped environments alongside terraform providers mirror.
Gotcha
When -plugin-dir is set, Terraform stops checking the registry entirely and dependency lock file verification is skipped, so make sure the directory actually has every provider version you need.
terraform providers lock -platform=linux_amd64 -platform=darwin_arm64 -platform=windows_amd64 ↓ Click command to explain
When to use this
Lock provider checksums for multiple operating systems and architectures at once, since developers on macOS and CI running on Linux both need matching entries in the lock file.
Gotcha
Running terraform providers lock with no -platform flag only adds entries for the platform you ran it on, which is why teams with mixed development machines and CI runners need to repeat the flag for each platform.
terraform get -update ↓ Click command to explain
When to use this
Re-download every referenced module at the newest version allowed by its version constraint, without touching provider or backend configuration.
terraform init -backend-config="bucket=my-tf-state" -backend-config="key=prod/terraform.tfstate" ↓ Click command to explain
When to use this
Provide backend configuration values on the command line instead of hardcoding them in the backend block, useful for keeping secrets out of .tf files.
terraform init -migrate-state ↓ Click command to explain
When to use this
Migrate existing state to a new backend when you are changing backend configuration.
Gotcha
Always back up your current state file before migrating backends. This copies state to the new location, but if anything goes wrong you need the backup.
terraform init -reconfigure ↓ Click command to explain
When to use this
Reinitialize the backend, ignoring any existing backend configuration, used when switching between backends.
terraform init -input=false ↓ Click command to explain
When to use this
Disable interactive prompts for backend configuration values, required in CI pipelines since there is no terminal to answer them.
Gotcha
Without -input=false, a CI job with a partially configured backend can appear to hang forever while it silently waits for input that will never arrive.
terraform init -get=false ↓ Click command to explain
When to use this
Skip downloading modules during init, useful when only reconfiguring the backend and modules are already present.
terraform init -backend=false ↓ Click command to explain
When to use this
Skip backend initialization entirely, useful when only working with modules locally or testing configuration without connecting to remote state.
Gotcha
Running plan or apply after -backend=false still fails, since those commands need a working backend. Use this only for quick local checks like validate or fmt.
terraform init -force-copy ↓ Click command to explain
When to use this
Skip the interactive yes or no prompt that normally appears when copying state to a new backend, useful for scripted backend migrations in CI.
Gotcha
This skips a safety confirmation, so only use it in a scripted migration you have already tested manually once.
terraform init -reconfigure -upgrade ↓ Click command to explain
When to use this
Reconfigure the backend and upgrade providers to the latest allowed versions in a single init call, common when switching backends and bumping provider versions at the same time.
terraform init -lock-timeout=5m ↓ Click command to explain
When to use this
Wait up to the given duration for the backend's state lock during init instead of failing immediately, useful when init runs right after another pipeline stage that briefly holds the lock.
TF_LOG=DEBUG terraform plan ↓ Click command to explain
When to use this
Enable verbose debug logging to diagnose provider errors, API call failures, or unexpected behavior.
Gotcha
The output is extremely verbose. Pipe it to a file with TF_LOG=DEBUG terraform plan 2> debug.log and search for the specific error rather than reading the whole output.
export TF_LOG=DEBUG && export TF_LOG_PATH=./terraform.log && terraform plan ↓ Click command to explain
When to use this
Write debug logs to a file instead of printing them to the terminal.
terraform validate -json ↓ Click command to explain
When to use this
Validate configuration and output results as JSON for parsing in CI pipelines.
terraform plan -detailed-exitcode ↓ Click command to explain
When to use this
Exit with code 0 if there are no changes, 1 if there is an error, and 2 if there are changes, useful in CI to distinguish success with no changes from success with pending changes.
Gotcha
Without -detailed-exitcode, terraform plan exits with 0 whether or not there are changes, so CI cannot tell the difference between a plan that succeeded with nothing to do and one that succeeded with changes waiting to be applied.
terraform apply -parallelism=5 ↓ Click command to explain
When to use this
Limit the number of concurrent operations Terraform performs, the default is 10, useful for rate-limited APIs.
Gotcha
Reducing parallelism slows down applies but can prevent API throttling errors from cloud providers.
TF_LOG=TRACE terraform apply ↓ Click command to explain
When to use this
Enable trace level logging, one level more detailed than DEBUG, used when debug logs are not detailed enough to diagnose a provider crash.
terraform plan -compact-warnings ↓ Click command to explain
When to use this
Collapse repeated warning messages into a single summary line, useful for large configurations where warnings would otherwise flood CI output.
terraform validate -no-color ↓ Click command to explain
When to use this
Disable ANSI color codes in validate output, needed when piping output into a log file or a CI system that does not render terminal colors.
Gotcha
Without -no-color, logs captured by some CI systems show raw escape codes mixed into the text instead of clean output.
TF_LOG_PROVIDER=DEBUG terraform plan ↓ Click command to explain
When to use this
Scope debug logging to only the communication between Terraform and provider plugins, producing a smaller and more focused log when the bug is clearly inside a provider.
TF_LOG_CORE=DEBUG terraform plan ↓ Click command to explain
When to use this
Scope debug logging to only Terraform core internals, excluding provider chatter, useful when the bug is in Terraform itself rather than a provider.
terraform apply -auto-approve -input=false ↓ Click command to explain
When to use this
Combine auto approval with disabled input prompts, the standard safe pairing for a CI pipeline apply step since a missing variable fails loudly instead of hanging.
Gotcha
Only use -auto-approve in a pipeline where the plan has already been reviewed as a separate step. Never combine it with a plan that has not been seen by a human.
terraform state list > /dev/null; echo $? ↓ Click command to explain
When to use this
Check whether a state command succeeded from within a script by testing its exit code, without needing to parse the actual output.
terraform plan -detailed-exitcode -no-color ↓ Click command to explain
When to use this
Combine a parseable exit code with disabled color output, the standard combination for CI systems that need both a reliable exit code and clean log text.
TF_DATA_DIR=/tmp/terraform-cache terraform init ↓ Click command to explain
When to use this
Override where Terraform stores its local .terraform working directory, used to isolate concurrent Terraform runs in the same CI workspace so parallel jobs do not overwrite each other's provider cache.
TF_CLI_ARGS_plan="-no-color" terraform plan ↓ Click command to explain
When to use this
Automatically inject a flag into every invocation of a specific subcommand, useful for enforcing -no-color or -input=false across an entire CI system without editing every script.
TF_IN_AUTOMATION=true terraform apply ↓ Click command to explain
When to use this
Tell Terraform it is running in a CI system rather than interactively, which trims some of the suggested next-command hints from output since no human is present to act on them.
Terraform is HashiCorp's infrastructure as code tool that lets you define cloud resources such as servers, networks, and databases in a declarative configuration language and have Terraform figure out how to create, update, or destroy the real infrastructure to match. Instead of clicking through a cloud console or writing imperative scripts that create resources step by step, you describe the end state you want, and Terraform computes the difference between that desired state and what actually exists, then applies only the changes needed. This declarative model is what makes Terraform valuable across almost every major cloud provider through the same consistent workflow, so a team that knows Terraform for AWS can apply the same commands and mental model to Azure, Google Cloud, or dozens of smaller providers with only the resource blocks changing.
The reason terraform commands appear in daily engineering work so often is that infrastructure, like application code, changes constantly. New environments get spun up for feature branches, security groups get tightened after an audit, and database instances get resized as traffic grows, and every one of those changes should go through the same reviewable plan and apply cycle rather than a manual console click that nobody can trace later. terraform plan and terraform apply together form the same kind of always reached for read and write loop that kubectl get and aws sts get-caller-identity represent in their own ecosystems, and most real Terraform usage in a mature team is those two commands run repeatedly against a growing set of modules and workspaces.
The single most important mental model for working with Terraform is the state file. Terraform does not inspect your cloud account from scratch on every run. It keeps a JSON record, usually stored remotely in an S3 bucket or Terraform Cloud, that maps every resource block in your configuration to the real object it created, and every plan is really a three way comparison between your configuration, that state file, and the actual infrastructure. Nearly every confusing Terraform error, from a resource that Terraform insists it needs to recreate to one it insists already exists, traces back to state being out of sync with reality in some way, which is exactly why terraform state list, terraform state show, and terraform plan are the first commands worth reaching for when something looks wrong.
Three mistakes account for most of the frustration engineers hit when learning Terraform. The first is running terraform apply without ever looking at the plan output first, since apply without a saved plan generates a brand new plan on the spot that may not match what was reviewed in a pull request. The second is manually editing or deleting resources in the cloud console after they were created by Terraform, which leaves the state file believing a resource exists when it does not, and the next plan either tries to recreate it or throws a confusing error. The third is running terraform destroy or terraform apply in the wrong workspace, because Terraform gives no visual warning about which workspace is active beyond the output of terraform workspace show, so always checking the active workspace before any destructive command is the single habit that prevents the most expensive version of this mistake.