terraform fmt automatically rewrites Terraform language files into the official canonical style. It directly improves code readability and keeps diffs stable.
The HashiCorp Terraform Associate exam frequently asks about the role of fmt, how it differs from validate, and how to use it in CI. This guide sticks to the stable, official behavior and turns it into knowledge you can apply directly at work.
terraform fmt rewrites Terraform language files such as .tf and .tfvars in place according to the official style. It does not change syntax or meaning — it only normalizes layout: whitespace, indentation, and line breaks.
On the Associate exam, you'll be asked questions like "which command unifies code style?" or "how do you detect formatting drift in CI and fail the build?" Be clear that fmt has a different role than syntax validation (validate) or planning execution (plan).
Basic usage
terraform fmt
terraform fmt main.tf
terraform fmt ./modules/networkIn production the combinations you'll reach for most are -recursive (recurse), -check (detect drift without rewriting), -diff (show diffs), -write=false (output only, no overwrite), and -list=false (suppress file name listing). Pick the right ones for your goal.
The standard CI approach is to detect drift and fail without rewriting files, optionally showing a diff. Locally, in-place rewriting is fine.
Commonly used command examples
# Recursively rewrite the whole repository in place (local work)
terraform fmt -recursive
# For CI: do not rewrite, show diffs, fail if anything is unformatted
terraform fmt -check -diff -recursive
# Keep logs clean (suppress file name listing)
terraform fmt -check -diff -list=false -recursive
# Preview only (do not overwrite). Best for a single file
terraform fmt -write=false main.tf > main.tf.previewIn CI, run terraform fmt -check -diff -recursive per pull request and fail the pipeline if anything is unformatted. With -diff, reviewers can see exactly what needs to change directly in the PR logs.
For consistent results across the team, use the same Terraform version line in CI and locally. The formatting rules are built into the official implementation, so no additional tools need to be installed.
Basic CI flow (example)
GitHub Actions example
name: terraform-fmt-check
on:
pull_request:
jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.x
- name: Check formatting
run: terraform fmt -check -diff -recursivefmt primarily targets Terraform language files (.tf, .tfvars, .auto.tfvars, etc.). The JSON variants (.tf.json / .tfvars.json) are out of scope. The contents of language literals such as template strings and heredocs are not modified in principle.
When recursing, fmt walks below the given directory. The .terraform directory that holds dependency modules is normally not version-controlled. In CI, it is safer to specify paths explicitly or use shell find to exclude it so it doesn't accidentally get processed.
Format while excluding the .terraform directory (bash example)
# Exclude .terraform and fmt each .tf found
find . -type d -name .terraform -prune -o -name '*.tf' -print0 | xargs -0 -n1 terraform fmtterraform fmt -write=false means "do not overwrite — print the formatted output to stdout". Applied across multiple files, the outputs concatenate, so it is safer to limit preview use to a single file. To see diffs, use -diff.
When diffs remain after formatting, the cause is often something outside fmt's scope — whitespace or newlines inside string literals, comment positions, etc. Also, subtle formatting differences can appear between Terraform major/minor versions, so aligning CLI versions across the team keeps things stable.
Heredoc contents are preserved (example)
resource "local_file" "example" {
content = <<-EOT
indented line
another spaced line
EOT
filename = "example.txt"
}
# fmt normalizes blocks and indentation, but whitespace inside the heredoc is preserved.A frequent Associate-level question is how fmt and validate divide responsibilities. fmt unifies style, validate performs syntax and some static checks, and plan creates an execution plan — three distinct purposes. Behavior does not change based on formatting, but for review-friendliness and stable diffs, fmt is essential.
Linters (e.g., tflint) check for best practices and policy compliance, but they are not part of the official CLI. On the exam, prioritize the roles of official commands when answering.
| Command / Tool | Primary Purpose | Overwrites Files | Typical Failure Condition |
|---|---|---|---|
| terraform fmt | Normalize style (format) | Yes by default (-write=false to disable) | Unformatted files (exits non-zero with -check) |
| terraform validate | Validate syntax, types, references | No | Syntax or reference errors detected |
| tflint (reference) | Best-practice checks via lint | No | Rule violations detected (depends on config) |
Minimal fmt → validate pipeline example
terraform fmt -recursive .
terraform validateAssociate
問題 1
In your team's CI, you want to fail the build when Terraform code isn't formatted in the official style, and show the required changes as a diff in the log. Which command is most appropriate?
正解: A
To detect unformatted files without rewriting them and show the required changes in CI, combining -check and -diff is the right choice. Use -recursive to cover subdirectories. -write=false only prints to stdout — it does not detect or fail on formatting drift. validate and plan have different purposes.
Does terraform fmt format .tf.json or .tfvars.json files?
No. terraform fmt targets Terraform language files (.tf, .tfvars, etc.) and does not format the JSON variants (.tf.json, .tfvars.json).
Is there a fixed exit code when unformatted files are detected?
terraform fmt formats files by default. When you pass -check, it exits with a non-zero code if any unformatted file is found. It is safer not to depend on a specific numeric value.
Where should terraform fmt run in a project?
Run it locally on save or before commit, and in CI run terraform fmt -check -diff -recursive on pull requests. In large repositories, explicitly scope the target directories and exclude artifacts like .terraform for safety.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...