100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

terraform validate and fmt

Understand two everyday Terraform commands — `terraform fmt` for consistent code style and `terraform validate` for catching syntax and configuration errors before you ever run a plan.

Testing & QualityBeginner6 min readJul 9, 2026
Analogies

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.

bash
$ 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 $?
3

terraform 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.

bash
$ 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 fmt rewrites files into canonical HCL style; -check makes it CI-friendly by failing without modifying files.
  • terraform validate checks syntax, references, and argument types locally, requiring terraform init but 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.
  • validate catches configuration-shape errors early but cannot catch provider-side logical errors like permission or capacity issues.
  • Consistent formatting via fmt reduces noisy diffs in code review and enforces a shared style across a team.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#TerraformValidateAndFmt#Terraform#Validate#Fmt#StudyNotes#SkillVeris#ExamPrep