Domain 3 of 8 · Chapter 3 of 7

Validate a configuration

What terraform validate checks, and what it can't

Suppose you rename a variable and forget to update one reference, or you pass a string where a resource expects a number. You want to catch that in a second, not after a slow plan or a half-finished apply. That is exactly what terraform validate is for: it runs checks that verify whether a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state[1].

What it checks

validate works only from your .tf files. It confirms three things: that the HashiCorp Configuration Language (HCL) parses (syntax), that the configuration hangs together (internal consistency, for example that a reference points at something that exists and that there are no dependency cycles), and that the attribute names and value types[1] you wrote match what the referenced resources and providers actually accept. A typo in an argument name, or a number supplied where a string is required, fails here.

What it deliberately does not check

The boundary is the whole point of the command: validate does not validate remote services, such as remote state or provider APIs[1]. It never reads your state file and never generates an execution plan, so it cannot tell you whether your credentials work, whether a name is still free, or whether a resource can actually be created. It also cannot see drift, because detecting drift means comparing against the real world, and validate never contacts the real world.

The practical consequence, and the single most common misconception, is that a passing validate does not promise a successful apply. It proves the configuration is well-formed and type-correct; proving it will actually build requires terraform plan and terraform apply. Read validate as the compiler-style check you run before you spend time planning.

validate checks (offline)HCL syntaxwell-formed blocksInternal consistencyreferences resolveAttribute names and typescorrect args, right typesneeds plan or applyProvider APIscredentials untestedRemote state and driftnot read hereReal resource creationonly apply proves it
What terraform validate checks from your files, versus what only plan or apply can confirm against real infrastructure.

Prerequisites: initialize first, then validate

validate is not the first command you run in a directory. Validation requires an initialized working directory with any referenced plugins and modules installed[1], because it cannot type-check against a provider whose schema it has not downloaded. On a fresh checkout, terraform validate fails until you run terraform init[2] first.

Initialize without a backend when you only want to type-check

If all you want is the static check, you do not need remote state configured. Run terraform init -backend=false[2], which installs the providers and modules but skips backend initialization. This is the usual setup in a continuous integration (CI) job whose only task is to validate a module: it avoids wiring up credentials for a backend the job will never touch.

Running it

Once the directory is initialized, terraform validate takes no target: it checks the configuration in the current directory. It is read-only and contacts nothing, so it returns almost immediately. Two options are worth knowing:

Option Effect
-json Emits the result as machine-readable JSON (covered in the next section).
-no-color Suppresses color codes, which keeps CI logs readable.

When validate finds a problem it reports an error with a source location, and Terraform does not continue validating once it catches an error[3], so you fix that error and re-run, repeating until the run is clean. The figure traces that loop: initialize once, validate, then either move on to terraform plan or fix and re-run.

terraform init-backend=false okterraform validateread-only checkErrors reported?Proceed to planor fmt, then commitFix, re-run validaterepeat until cleanNoYes
Initialize the directory once, then validate; a clean run leads to plan, while errors send you back to fix and re-run.

Machine-readable output for automation

The reason validate fits cleanly into pipelines is its structured output. It is safe to run this command automatically, for example as a post-save check in a text editor or as a test step for a reusable module in a CI system[1], and the -json flag turns its result into a stable object a script can parse.

The -json result object

terraform validate -json prints a single JSON object. Its top-level fields are:

Field Type Meaning
format_version string Output format version, "1.0" since Terraform 1.1.0.
valid bool Whether the configuration passed.
error_count number How many errors were found.
warning_count number How many warnings were found.
diagnostics array One object per error or warning.

Each entry in diagnostics[1] carries a severity of "error" or "warning", a short summary, an optional detail, and an optional range locating the offending source by filename with start and end positions. A script decides pass or fail by reading valid (or error_count) and can surface diagnostics inline in a pull request. The figure lays out that object and its nested diagnostic fields.

Validate as a module's unit test

validate is primarily useful for general verification of reusable modules[1]. A module author cannot run a real plan for every consumer, but validate confirms, cheaply and offline, that the module's own attribute names and value types are internally correct. Wiring terraform init -backend=false && terraform validate into CI gives every push a fast structural gate that needs no cloud credentials.

validate -jsonformat_version"1.0"validtrue or falseerror_countnumberwarning_countnumberdiagnostics[]arrayseverityerror or warningsummaryshort messagedetailoptionalrangefilename, line
The terraform validate -json object: summary fields plus a diagnostics array whose entries carry severity, summary, detail, and range.

Exam-pattern recognition

TA-004 items on validate are definitional and lean on one boundary: what a static, offline check can and cannot prove. Keep that boundary sharp and the questions answer themselves.

A common stem describes a symptom and asks whether terraform validate would catch it. If the symptom is structural (a wrong attribute name, a type mismatch, an unresolved reference, a dependency cycle), validate catches it. If the symptom needs the real world (bad credentials, a name already taken, a quota exceeded, drift since the last apply), validate does not, because it never contacts provider APIs or remote state. The trap answer claims a clean validate guarantees a successful apply; reject it, since validate proves form and types only.

Another stem gives a fresh checkout and a failing terraform validate and asks why. The answer is that the directory is not initialized: run terraform init (or terraform init -backend=false) first so the providers and modules are installed. A distractor suggests running terraform plan or terraform refresh to fix it, but those also need an initialized directory and do far more than validate asks.

A CI-flavored stem asks how to check a module without cloud access. The answer pairs terraform init -backend=false with terraform validate, optionally -json for machine-readable output. Distractors reach for terraform plan, which contacts real infrastructure, or terraform fmt, which only fixes formatting and does not verify names or types.

Finally, watch the validate-versus-fmt-versus-plan distinction. terraform fmt rewrites style, terraform validate checks static correctness without touching infrastructure, and terraform plan compares your configuration against refreshed, real state. A question that asks which command previews real changes wants plan, not validate.

Three configuration checks, ordered by depth

Aspectterraform fmtterraform validateterraform plan
What it checksFormatting and style onlySyntax, internal consistency, attribute names and value typesDesired configuration against real, refreshed state
Needs terraform init first?NoYes, providers and modules must be installedYes
Contacts provider APIs or state?NoNoYes, refreshes state by default
Changes anything?Rewrites file style unless -check or -write=falseNo, read-onlyNo, preview only
Typical useCanonical formatting before commitFast correctness check in CI or an editorReview the real changes before apply

Decision tree

Change or previewreal infrastructure?terraform planpreview vs real stateOnly reformatting style?terraform fmtstyle onlyDirectory initialized?terraform validatestatic, offline checkterraform init firstor -backend=falseYesNoYesNoYesNo

Sharp facts the exam loves — give these one last read before exam day.

Cheat sheet

Sharp facts the exam loves — scan these before test day.

validate checks syntax and internal consistency

terraform validate verifies that a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state.

13 questions test this
validate checks attribute names and value types

terraform validate confirms that argument names and value types are correct for the resources and providers referenced, catching type mismatches and unknown attributes before a plan.

8 questions test this
validate does not check remote services

terraform validate does not validate remote services such as provider APIs or remote state, so it cannot confirm that credentials work or that a resource can actually be created.

Trap Assuming a passing validate guarantees a successful apply; it checks configuration correctness only, not real infrastructure or API access.

11 questions test this
validate is not a plan

terraform validate does not read state or generate an execution plan, so it will not surface drift or runtime errors that only appear when Terraform contacts real infrastructure.

validate requires an initialized directory

terraform validate requires an already-initialized working directory with referenced providers and modules installed; run terraform init (optionally with -backend=false) first.

Trap Thinking validate works on a fresh checkout without init; it needs providers and modules installed to type-check the configuration.

12 questions test this
validate supports JSON output and CI use

terraform validate -json produces machine-readable output, and the command is safe to run automatically, for example as an editor post-save check or a CI test step for a reusable module.

References

  1. Command: terraform validate
  2. Command: terraform init
  3. Tutorial: Troubleshoot Terraform (validate workflow)