{"record":{"id":"a668726d324c91ec","repo":"hashicorp/terraform","slug":"only-tf-tfvars-and-tftest-hcl-files-can-be-pr","errorCode":null,"errorMessage":"Only .tf, .tfvars, and .tftest.hcl files can be processed with terraform fmt","messagePattern":"Only \\.tf, \\.tfvars, and \\.tftest\\.hcl files can be processed with terraform fmt","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/fmt.go","lineNumber":163,"sourceCode":"\t\t\t\t\t\t// so we'll need to simplify here.\n\t\t\t\t\t\tdiags = diags.Append(fmt.Errorf(\"Failed to read file %s\", path))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tfileDiags := c.processFile(c.normalizePath(path), f, stdout, false)\n\t\t\t\t\tdiags = diags.Append(fileDiags)\n\t\t\t\t\tf.Close()\n\n\t\t\t\t\t// Take note that we processed the file.\n\t\t\t\t\tfmtd = true\n\n\t\t\t\t\t// Don't check the remaining extensions.\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif !fmtd {\n\t\t\t\tdiags = diags.Append(fmt.Errorf(\"Only .tf, .tfvars, and .tftest.hcl files can be processed with terraform fmt\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\n\treturn diags\n}\n\nfunc (c *FmtCommand) processFile(path string, r io.Reader, w io.Writer, isStdout bool) tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\n\tlog.Printf(\"[TRACE] terraform fmt: Formatting %s\", path)\n\n\tsrc, err := io.ReadAll(r)\n\tif err != nil {\n\t\tdiags = diags.Append(fmt.Errorf(\"Failed to read %s\", path))\n\t\treturn diags\n\t}","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/fmt.go#L145-L181","documentation":"Thrown by `terraform fmt` when a path passed on the command line refers to a regular file whose name does not end in one of the supported extensions (.tf, .tfvars, .tftest.hcl). The command iterates fmtSupportedExts; if none match, fmtd stays false and the file is rejected. This guards the formatter from operating on non-HCL files where formatting would be meaningless or destructive.","triggerScenarios":"Running `terraform fmt main.tf.json`, `terraform fmt README.md`, `terraform fmt script.sh`, or passing any file with an unsupported extension directly (not a directory). Directory traversal (processDir) skips non-matching files silently, so this only fires for explicit file arguments.","commonSituations":"Passing a JSON-syntax Terraform file (.tf.json) which is NOT supported by fmt; passing a .sh hook script; mistyping a filename; attempting to format a generated file like .terraform.lock.hcl.","solutions":["Rename or restrict the argument to a file with a .tf, .tfvars, or .tftest.hcl extension.","If formatting a directory, pass the directory path instead of individual non-HCL files so unsupported files are skipped automatically.","Convert JSON-syntax config (.tf.json) to native HCL (.tf) before formatting, since fmt does not support JSON syntax."],"exampleFix":"// before\n$ terraform fmt main.tf.json\n// after\n$ terraform fmt main.tf","handlingStrategy":"validation","validationCode":"// Before calling fmt on a path, verify the extension is supported.\nfunc isFmtSupported(path string) bool {\n    for _, ext := range []string{\".tf\", \".tfvars\", \".tftest.hcl\"} {\n        if strings.HasSuffix(path, ext) {\n            return true\n        }\n    }\n    return false\n}\n// usage:\n// if !isFmtSupported(p) { return fmt.Errorf(\"skip: %s unsupported\", p) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Glob inputs with supported extensions before invoking fmt: *.tf, *.tfvars, *.tftest.hcl.","Do not pass .tf.json files to fmt; convert them to native HCL first.","Prefer directory arguments over individual files so unsupported files are skipped silently."],"tags":["terraform-fmt","file-extension","cli","validation"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}