hashicorp/terraform · info

Only .tf, .tfvars, and .tftest.hcl files can be processed wi

Error message

Only .tf, .tfvars, and .tftest.hcl files can be processed with terraform fmt

What it means

Returned by FmtCommand.fmt (fmt.go:163) when a target is a regular file (not a directory) whose extension is not in fmtSupportedExts (.tf, .tfvars, .tftest.hcl, .tfmock.hcl, .tfquery.hcl). fmt refuses to process unrelated files to avoid mangling non-HCL content. The message lists the canonical subset even though the internal list now also includes .tfmock.hcl and .tfquery.hcl.

Source

Thrown at internal/command/fmt.go:163

						// so we'll need to simplify here.
						diags = diags.Append(fmt.Errorf("Failed to read file %s", path))
						continue
					}

					fileDiags := c.processFile(c.normalizePath(path), f, stdout, false)
					diags = diags.Append(fileDiags)
					f.Close()

					// Take note that we processed the file.
					fmtd = true

					// Don't check the remaining extensions.
					break
				}
			}

			if !fmtd {
				diags = diags.Append(fmt.Errorf("Only .tf, .tfvars, and .tftest.hcl files can be processed with terraform fmt"))
				continue
			}
		}
	}

	return diags
}

func (c *FmtCommand) processFile(path string, r io.Reader, w io.Writer, isStdout bool) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	log.Printf("[TRACE] terraform fmt: Formatting %s", path)

	src, err := io.ReadAll(r)
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to read %s", path))
		return diags
	}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Only pass .tf, .tfvars, .tftest.hcl, .tfmock.hcl, or .tfquery.hcl files to fmt.
  2. For JSON config files (.tf.json etc.), format the JSON manually with `jq .` or your editor — fmt does not touch JSON.
  3. If you meant to format a directory, pass the directory (not individual non-tf files): `terraform fmt ./modules`.
  4. Filter globs: `terraform fmt *.tf *.tfvars` instead of `terraform fmt *`.

Example fix

# before
terraform fmt variables.tf.json
# Only .tf, .tfvars, and .tftest.hcl files can be processed with terraform fmt

# after
terraform fmt variables.tf        # native HCL
jq . variables.tf.json > tmp && mv tmp variables.tf.json  # format JSON separately
Defensive patterns

Strategy: type-guard

Validate before calling

// Filter inputs to supported extensions before calling fmt
var valid []string
for _, p := range paths {
    if isFmtSupported(p) { valid = append(valid, p) } else {
        log.Printf("skipping unsupported file: %s", p)
    }
}
if len(valid) == 0 { return errors.New("no fmt-supported files supplied") }

Type guard

// isFmtSupported reports whether path has an extension terraform fmt will process.
func isFmtSupported(path string) bool {
    for _, ext := range []string{".tf", ".tfvars", ".tftest.hcl", ".tfmock.hcl", ".tfquery.hcl"} {
        if strings.HasSuffix(path, ext) { return true }
    }
    return false
}

Prevention

When it happens

Trigger: Pointing fmt at a file like README.md, main.tf.json, variables.auto.tfvars.json, policy.json, or any file with a non-supported extension. fmt loops fmtSupportedExts, finds no match, sets fmtd=false, and appends this diagnostic.

Common situations: Running `terraform fmt .` in a directory and pointing it directly at a .tf.json file (JSON config is not formatted by fmt); passing a .md or .txt doc by mistake; globbing `terraform fmt *.json`; users expecting fmt to handle JSON variant files.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/a668726d324c91ec. Report an issue: GitHub.