terraform validate and fmt
Before a plan ever touches a provider API, two lightweight commands help keep a Terraform codebase clean and correct: terraform fmt, which rewrites configuration files into the canonical HCL style, and terraform validate, which checks that the configuration is internally consistent — correct syntax, valid attribute references, and correct argument types — without contacting any remote provider or reading real infrastructure. Both commands are fast, local, and safe to run constantly, which is why teams typically wire them into pre-commit hooks and the first stage of every CI pipeline.
Cricket analogy: Before a match ball is even bowled, two cheap checks help: inspecting the pitch for visible cracks, and checking the team sheet's eligibility rules against the tournament regulations — neither requires actually playing a ball, so umpires run them before every single game.
terraform fmt
terraform fmt normalizes indentation, alignment of = signs, and spacing according to HCL's canonical style. It rewrites files in place by default. Running it with -recursive formats every .tf file in subdirectories, and -check makes it exit non-zero if any file is not already formatted — the flag CI pipelines use to fail a build without silently rewriting the developer's code.
Cricket analogy: A tournament's style guide normalizes how every scorecard lists batting order and extras, rewriting sloppy entries automatically by default, and a strict '-check' mode at the gate rejects any scorecard submitted out of format instead of silently fixing it for the scorer.
$ terraform fmt -recursive -check -diff
modules/network/main.tf
--- old/modules/network/main.tf
+++ new/modules/network/main.tf
@@ -3,7 +3,7 @@
resource "aws_vpc" "main" {
- cidr_block = "10.0.0.0/16"
- tags = {
+ cidr_block = "10.0.0.0/16"
+ tags = {
Name = "main-vpc"
}
}
$ echo $?
3terraform validate
terraform validate parses the configuration, checks that referenced variables, resources, and modules exist, verifies argument types against the provider schema, and reports errors with file and line context. It requires terraform init to have been run first (so provider schemas are available) but does not require valid credentials, since it never calls the provider's remote API — it only checks configuration shape, not real-world state.
Cricket analogy: An umpire reviewing a team sheet checks that every named player, substitute, and role actually exists and matches the tournament roster, flagging exact discrepancies by name — but this requires the tournament roster to already be loaded, and never involves actually calling the player's phone to confirm.
$ terraform validate
╗ Error: Unsupported argument
on main.tf line 12, in resource "aws_instance" "web":
12: instance_typ = "t3.micro"
An argument named "instance_typ" is not expected here. Did you mean
"instance_type"?Think of fmt as a linter for style and validate as a linter for correctness — neither one talks to AWS, Azure, or GCP, so both are safe to run offline, in a sandbox, or as a fast pre-commit gate with zero risk to real infrastructure.
terraform validate cannot catch every real-world problem: it will not detect that an IAM role lacks a permission, that a CIDR block overlaps an existing VPC, or that a resource name collides — those errors only surface during plan or apply against the real provider.
terraform fmtrewrites files into canonical HCL style;-checkmakes it CI-friendly by failing without modifying files.terraform validatechecks syntax, references, and argument types locally, requiringterraform initbut no cloud credentials.- Neither command contacts a remote provider API or inspects real infrastructure state.
- Both are cheap enough to run on every commit, making them ideal as the first stage of a CI pipeline.
validatecatches configuration-shape errors early but cannot catch provider-side logical errors like permission or capacity issues.- Consistent formatting via
fmtreduces noisy diffs in code review and enforces a shared style across a team.
Practice what you learned
1. What does `terraform fmt -check` do differently from plain `terraform fmt`?
2. Does `terraform validate` require valid cloud provider credentials to run?
3. Which of these errors WILL `terraform validate` catch?
4. What must be run before `terraform validate` will work correctly?
5. Why do teams commonly run `terraform fmt -check` and `terraform validate` as the first CI stage?
Was this page helpful?
You May Also Like
HCL Syntax Fundamentals
HashiCorp Configuration Language (HCL) is the declarative syntax underlying every Terraform file. Mastering its blocks, arguments, and expressions is the foundation for writing correct configurations.
terraform init, plan, and apply
The three-command core workflow of Terraform: init downloads dependencies, plan previews changes, and apply executes them -- forming a safe, repeatable provisioning cycle.
Terraform in CI/CD Pipelines
Learn the standard stages, safety controls, and credential-handling patterns for running Terraform reliably inside a CI/CD pipeline, from plan-on-PR to gated apply-on-merge.
Common Terraform Pitfalls
A field guide to the mistakes Terraform users make most often — from state file mishandling to accidental destroys — and how to avoid each one.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics