{"record":{"id":"98518fcb474e12ec","repo":"hashicorp/terraform","slug":"failed-to-read-file-s","errorCode":null,"errorMessage":"Failed to read file %s","messagePattern":"Failed to read file (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/command/fmt.go","lineNumber":146,"sourceCode":"\tfor _, path := range paths {\n\t\tpath = c.normalizePath(path)\n\t\tinfo, err := os.Stat(path)\n\t\tif err != nil {\n\t\t\tdiags = diags.Append(fmt.Errorf(\"No file or directory at %s\", path))\n\t\t\treturn diags\n\t\t}\n\t\tif info.IsDir() {\n\t\t\tdirDiags := c.processDir(path, stdout)\n\t\t\tdiags = diags.Append(dirDiags)\n\t\t} else {\n\t\t\tfmtd := false\n\t\t\tfor _, ext := range fmtSupportedExts {\n\t\t\t\tif strings.HasSuffix(path, ext) {\n\t\t\t\t\tf, err := os.Open(path)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t// Open does not produce error messages that are end-user-appropriate,\n\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","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/fmt.go#L128-L164","documentation":"Thrown by FmtCommand.fmt when os.Open fails on a file that (a) exists per os.Stat and (b) matches a fmt-supported extension (.tf, .tfvars, .tftest.hcl). The comment notes os.Open's raw error is not end-user-friendly, so Terraform substitutes this generic message. The loop continues to other files.","triggerScenarios":"Stat succeeded (file existed) but by the time Open ran the file was removed (TOCTOU race); the file's permissions allow stat but not read; the path is a broken symlink that stat resolved but open cannot follow; the file is a special device.","commonSituations":"File mode denies read to the user (stat ok, open EACCES); a concurrent process deleted the file between stat and open; symlink to a missing target where lstat/stat semantics differ; SELinux denying read.","solutions":["Confirm read permission: `cat <path>` or `test -r <path> && echo ok`.","chmod to grant read: `chmod u+r <path>`.","If a race deleted the file, rerun after stabilizing the directory.","Check SELinux/AppArmor for read denials (`ls -Z`, audit logs)."],"exampleFix":"// before: file is 0000, stat ok but open fails\n//   $ chmod u+r main.tf\n// after: terraform fmt main.tf succeeds","handlingStrategy":"validation","validationCode":"func openable(p string) error {\n    f, err := os.Open(p)\n    if err != nil { return fmt.Errorf(\"%s not readable: %w\", p, err) }\n    f.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure read permission (u+r) on .tf/.tfvars files before fmt.","Avoid races where files are deleted between stat and open.","Check SELinux/AppArmor if reads fail despite Unix perms."],"tags":["fmt","cli","filesystem","permissions","race"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}